From 4ff36c07f433e6048b76f2bf8cc79b5dd2c058c2 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 1 Jun 2022 11:44:49 +0200 Subject: [PATCH 001/114] Test suspend/resume feature for Audiobridge --- .../audiobridge/html/audiobridge-client.js | 39 ++++++++++++ examples/audiobridge/src/index.js | 40 ++++++++++++ src/plugins/audiobridge-plugin.js | 63 ++++++++++++++++++- 3 files changed, 140 insertions(+), 2 deletions(-) diff --git a/examples/audiobridge/html/audiobridge-client.js b/examples/audiobridge/html/audiobridge-client.js index 71fdc2b..c8c1ec7 100644 --- a/examples/audiobridge/html/audiobridge-client.js +++ b/examples/audiobridge/html/audiobridge-client.js @@ -10,6 +10,7 @@ let pendingOfferMap = new Map(); const myRoom = getURLParameter('room') ? parseInt(getURLParameter('room')) : (getURLParameter('room_str') || 1234); const randName = ('John_Doe_' + Math.floor(10000 * Math.random())); const myName = getURLParameter('name') || randName; +let myFeed; const skipJoin = getURLParameter('skipjoin') || false; const skipOffer = getURLParameter('skipoffer') || false; @@ -237,6 +238,35 @@ function _listForward({ room = myRoom, secret = 'adminpwd' } = {}) { }); } +function _suspend({ room = myRoom, feed = myFeed, stop_record = false, secret = 'adminpwd' } = {}) { + let suspendData = { + room, + feed, + stop_record, + secret, + }; + + socket.emit('suspend-peer', { + data: suspendData, + _id: getId(), + }); +} + +function _resume({ room = myRoom, feed = myFeed, record = false, filename, secret = 'adminpwd' } = {}) { + let resumeData = { + room, + feed, + record, + secret, + }; + if (filename) resumeData.filename = filename; + + socket.emit('resume-peer', { + data: resumeData, + _id: getId(), + }); +} + socket.on('connect', () => { console.log('socket connected'); socket.sendBuffer = []; @@ -267,6 +297,7 @@ socket.on('audiobridge-error', ({ error, _id }) => { socket.on('joined', async ({ data }) => { console.log('you have joined to room', data); + myFeed = data.feed; removeAllAudioElements(); closePC(); setAudioElement(null, data.feed, data.display, data.room); @@ -343,6 +374,14 @@ socket.on('peer-talking', ({ data }) => { console.log('peer talking notify', data); }); +socket.on('peer-suspended', ({ data }) => { + console.log('peer suspended notify', data); +}); + +socket.on('peer-resumed', ({ data }) => { + console.log('peer resumed notify', data); +}); + socket.on('exists', ({ data }) => { console.log('room exists', data); }); diff --git a/examples/audiobridge/src/index.js b/examples/audiobridge/src/index.js index 91cbbb6..ebabb2d 100644 --- a/examples/audiobridge/src/index.js +++ b/examples/audiobridge/src/index.js @@ -167,6 +167,16 @@ function initFrontEnd() { replyEvent(socket, 'peer-talking', evtdata); }); + + audioHandle.on(AudioBridgePlugin.EVENT.AUDIOBRIDGE_PEER_SUSPENDED, evtdata => { + replyEvent(socket, 'peer-suspended', evtdata); + }); + + + audioHandle.on(AudioBridgePlugin.EVENT.AUDIOBRIDGE_PEER_RESUMED, evtdata => { + replyEvent(socket, 'peer-resumed', evtdata); + }); + // generic audiobridge events audioHandle.on(Janode.EVENT.HANDLE_WEBRTCUP, () => Logger.info(`${LOG_NS} ${audioHandle.name} webrtcup event`)); audioHandle.on(Janode.EVENT.HANDLE_MEDIA, evtdata => Logger.info(`${LOG_NS} ${audioHandle.name} media event ${JSON.stringify(evtdata)}`)); @@ -415,6 +425,36 @@ function initFrontEnd() { } }); + socket.on('suspend-peer', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} suspend-peer received`); + const { _id, data: suspendpeerdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + await janodeManagerHandle.suspend(suspendpeerdata); + replyEvent(socket, 'peer-suspended', {}, _id); + Logger.info(`${LOG_NS} ${remote} peer-suspended sent`); + } catch ({ message }) { + replyError(socket, message, suspendpeerdata, _id); + } + }); + + socket.on('resume-peer', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} resume-peer received`); + const { _id, data: resumepeerdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + await janodeManagerHandle.resume(resumepeerdata); + replyEvent(socket, 'peer-resumed', {}, _id); + Logger.info(`${LOG_NS} ${remote} peer-resumed sent`); + } catch ({ message }) { + replyError(socket, message, resumepeerdata, _id); + } + }); + }); // disable caching for all app diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index 7932754..14e32e1 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -25,6 +25,8 @@ const REQUEST_ALLOW = 'allowed'; const REQUEST_RTP_FWD_START = 'rtp_forward'; const REQUEST_RTP_FWD_STOP = 'stop_rtp_forward'; const REQUEST_RTP_FWD_LIST = 'listforwarders'; +const REQUEST_SUSPEND_PARTICIPANT = 'suspend'; +const REQUEST_RESUME_PARTICIPANT = 'resume'; /* These are the events/responses that the Janode plugin will manage */ /* Some of them will be exported in the plugin descriptor */ @@ -41,6 +43,8 @@ const PLUGIN_EVENT = { PEER_KICKED: 'audiobridge_peer_kicked', TALKING: 'audiobridge_talking', PEER_TALKING: 'audiobridge_peer_talking', + PEER_SUSPENDED: 'audiobridge_peer_suspended', + PEER_RESUMED: 'audiobridge_peer_resumed', EXISTS: 'audiobridge_exists', ROOMS_LIST: 'audiobridge_list', CREATED: 'audiobridge_created', @@ -171,7 +175,7 @@ class AudioBridgeHandle extends Handle { janode_event.data.feed = message_data.id; if (typeof message_data.rtp !== 'undefined') janode_event.data.rtp = message_data.rtp; /* Add participants data */ - janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking }) => { + janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking, suspended }) => { const peer = { feed: id, display, @@ -179,6 +183,7 @@ class AudioBridgeHandle extends Handle { setup, }; if (typeof talking !== 'undefined') peer.talking = talking; + if (typeof suspended !== 'undefined') peer.suspended = suspended; return peer; }); janode_event.event = PLUGIN_EVENT.JOINED; @@ -189,13 +194,14 @@ class AudioBridgeHandle extends Handle { if (typeof message_data.participants[0].display === 'string') janode_event.data.display = message_data.participants[0].display; if (typeof message_data.participants[0].muted !== 'undefined') janode_event.data.muted = message_data.participants[0].muted; if (typeof message_data.participants[0].setup !== 'undefined') janode_event.data.setup = message_data.participants[0].setup; + if (typeof message_data.participants[0].suspended !== 'undefined') janode_event.data.suspended = message_data.participants[0].suspended; janode_event.event = PLUGIN_EVENT.PEER_JOINED; } break; /* Participants list */ case 'participants': - janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking }) => { + janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking, suspended }) => { const peer = { feed: id, display, @@ -203,6 +209,7 @@ class AudioBridgeHandle extends Handle { setup, }; if (typeof talking !== 'undefined') peer.talking = talking; + if (typeof suspended !== 'undefined') peer.suspended = suspended; return peer; }); janode_event.event = PLUGIN_EVENT.PARTICIPANTS_LIST; @@ -279,6 +286,7 @@ class AudioBridgeHandle extends Handle { if (typeof message_data.participants[0].display === 'string') janode_event.data.display = message_data.participants[0].display; if (typeof message_data.participants[0].muted !== 'undefined') janode_event.data.muted = message_data.participants[0].muted; if (typeof message_data.participants[0].setup !== 'undefined') janode_event.data.setup = message_data.participants[0].setup; + if (typeof message_data.participants[0].suspended !== 'undefined') janode_event.data.suspended = message_data.participants[0].suspended; janode_event.event = PLUGIN_EVENT.PEER_CONFIGURED; break; } @@ -302,6 +310,18 @@ class AudioBridgeHandle extends Handle { } break; } + /* A participant has been suspended */ + if (typeof message_data.suspended != 'undefined') { + janode_event.data.feed = message_data.suspended; + janode_event.event = PLUGIN_EVENT.PEER_SUSPENDED; + break; + } + /* A participant has been resumed */ + if (typeof message_data.resumed != 'undefined') { + janode_event.data.feed = message_data.resumed; + janode_event.event = PLUGIN_EVENT.PEER_RESUMED; + break; + } } /* The event has been handled */ @@ -740,6 +760,41 @@ class AudioBridgeHandle extends Handle { throw (error); } + async suspend({ room, feed, stop_record, secret }) { + const body = { + request: REQUEST_SUSPEND_PARTICIPANT, + room, + id: feed + }; + if (typeof stop_record === 'boolean') body.stop_record = stop_record; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.SUCCESS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + async resume({ room, feed, record, filename, secret }) { + const body = { + request: REQUEST_RESUME_PARTICIPANT, + room, + id: feed + }; + if (typeof record === 'boolean') body.record = record; + if (typeof filename === 'string') body.filename = filename; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.SUCCESS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + } /** @@ -996,6 +1051,10 @@ export default { */ AUDIOBRIDGE_PEER_TALKING: PLUGIN_EVENT.PEER_TALKING, + AUDIOBRIDGE_PEER_SUSPENDED: PLUGIN_EVENT.PEER_SUSPENDED, + + AUDIOBRIDGE_PEER_RESUMED: PLUGIN_EVENT.PEER_RESUMED, + /** * Generic audiobridge error. * From f7f765fc85f16242e4c3815e289f6f987d310f04 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 20 Jan 2023 12:48:06 +0100 Subject: [PATCH 002/114] videoroom: add private_id feature and multistream "update" api --- src/plugins/videoroom-plugin.js | 55 ++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 3eda329..b0e6a30 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -23,6 +23,7 @@ const REQUEST_SWITCH = 'switch'; const REQUEST_PUBLISH = 'publish'; const REQUEST_UNPUBLISH = 'unpublish'; const REQUEST_LEAVE = 'leave'; +const REQUEST_UPDATE = 'update'; const REQUEST_EXISTS = 'exists'; const REQUEST_LIST_ROOMS = 'list'; @@ -182,12 +183,14 @@ class VideoRoomHandle extends Handle { janode_event.data.feed = message_data.id; janode_event.data.description = message_data.description; - janode_event.data.publishers = message_data.publishers.map(({ id, display, talking }) => { + janode_event.data.private_id = message_data.private_id; + janode_event.data.publishers = message_data.publishers.map(({ id, display, talking, streams }) => { const pub = { feed: id, display, }; if (typeof talking !== 'undefined') pub.talking = talking; + if (typeof streams !== 'undefined') pub.streams = streams; return pub; }); janode_event.event = PLUGIN_EVENT.PUB_JOINED; @@ -382,12 +385,13 @@ class VideoRoomHandle extends Handle { /* Publisher list notification */ if (message_data.publishers) { janode_event.event = PLUGIN_EVENT.PUB_LIST; - janode_event.data.publishers = message_data.publishers.map(({ id, display, talking }) => { + janode_event.data.publishers = message_data.publishers.map(({ id, display, talking, streams }) => { const pub = { feed: id, display, }; if (typeof talking !== 'undefined') pub.talking = talking; + if (typeof streams !== 'undefined') pub.streams = streams; return pub; }); break; @@ -764,13 +768,14 @@ class VideoRoomHandle extends Handle { * @param {boolean} [params.audio] - True to subscribe to the audio feed * @param {boolean} [params.video] - True to subscribe to the video feed * @param {boolean} [params.data] - True to subscribe to the datachannels of the feed + * @param {number} [params.private_id] - The private id to correlate with publisher * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled * @param {string} [params.token] - The optional token needed * @returns {Promise} */ - async joinSubscriber({ room, feed, audio, video, data, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, token }) { + async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, token }) { const body = { request: REQUEST_JOIN, ptype: PTYPE_LISTENER, @@ -780,6 +785,7 @@ class VideoRoomHandle extends Handle { if (typeof audio === 'boolean') body.audio = audio; if (typeof video === 'boolean') body.video = video; if (typeof data === 'boolean') body.data = data; + if (typeof private_id === 'number') body.private_id = private_id; if (typeof token === 'string') body.token = token; if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; @@ -887,6 +893,27 @@ class VideoRoomHandle extends Handle { throw (error); } + /** + * [multistream] Update a subscription. + * + * @returns {Promise} + */ + async update({ subscribe, unsubscribe }) { + const body = { + request: REQUEST_UPDATE, + }; + if (Array.isArray(subscribe)) body.subscribe = subscribe; + if (Array.isArray(unsubscribe)) body.unsubscribe = unsubscribe; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.UPDATED) { + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + /*----------------*/ /* Management API */ /*----------------*/ @@ -1029,6 +1056,7 @@ class VideoRoomHandle extends Handle { * @param {boolean} [params.talking_events] - True to enable talking events * @param {number} [params.talking_level_threshold] - Audio level threshold for talking events in the range [0, 127] * @param {number} [params.talking_packets_threshold] - Audio packets threshold for talking events + * @param {boolean} [params.require_pvtid] - whether subscriptions are required to provide a valid private_id * @param {boolean} [params.record] - Wheter to enable recording of any publisher * @param {string} [params.rec_dir] - Folder where recordings should be stored * @param {boolean} [params.videoorient] - Whether the video-orientation RTP extension must be negotiated @@ -1036,7 +1064,8 @@ class VideoRoomHandle extends Handle { * @returns {Promise} */ async create({ room, description, max_publishers, permanent, is_private, secret, pin, bitrate, - bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, record, rec_dir, videoorient, h264_profile }) { + bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, + require_pvtid, record, rec_dir, videoorient, h264_profile }) { const body = { request: REQUEST_CREATE, }; @@ -1055,6 +1084,7 @@ class VideoRoomHandle extends Handle { if (typeof talking_events === 'boolean') body.audiolevel_event = talking_events; if (typeof talking_level_threshold === 'number' && talking_level_threshold >= 0 && talking_level_threshold <= 127) body.audio_level_average = talking_level_threshold; if (typeof talking_packets_threshold === 'number' && talking_packets_threshold > 0) body.audio_active_packets = talking_packets_threshold; + if (typeof require_pvtid === 'boolean') body.require_pvtid = require_pvtid; if (typeof record === 'boolean') body.record = record; if (typeof rec_dir === 'string') body.rec_dir = rec_dir; if (typeof videoorient === 'boolean') body.videoorient_ext = videoorient; @@ -1231,9 +1261,11 @@ class VideoRoomHandle extends Handle { * @property {number|string} feed - The feed identifier * @property {string} [display] - The dsplay name, if available * @property {string} description - A description of the room, if available + * @property {number} private_id - The private id that can be used when subscribing * @property {object[]} publishers - The list of active publishers * @property {number|string} publishers[].feed - The feed of an active publisher * @property {string} publishers[].display - The display name of an active publisher + * @property {object[]} [publishers[].streams] - [multistream] streams description * @property {RTCSessionDescription} [jsep] - The JSEP answer */ @@ -1417,6 +1449,15 @@ class VideoRoomHandle extends Handle { * @property {boolean} recording - Whether or not the room recording is now enabled */ +/** + * [multistream] The response event for update subscriber request. + * + * @typedef {object} VIDEOROOM_EVENT_UPDATED + * @property {number|string} room - The involved room + * @property {RTCSessionDescription} [jsep] - The updated JSEP offer + * @property {object[]} streams - List of the updated streams in this subscription + */ + /** * The exported plugin descriptor. * @@ -1460,6 +1501,7 @@ export default { * @property {object[]} publishers - List of the new publishers * @property {number|string} publishers[].feed - Feed identifier of the new publisher * @property {string} publishers[].display - Display name of the new publisher + * @property {object[]} [publishers[].streams] - [multistream] streams description */ VIDEOROOM_PUB_LIST: PLUGIN_EVENT.PUB_LIST, @@ -1571,10 +1613,7 @@ export default { * A multistream subscription has been updated. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UPDATED - * @type {object} - * @property {number|string} room - The involved room - * @param {RTCSessionDescription} [jsep] - The updated JSEP offer - * @param {object[]} streams - List of the streams in this subscription + * @type {module:videoroom-plugin~VIDEOROOM_EVENT_UPDATED} */ VIDEOROOM_UPDATED: PLUGIN_EVENT.UPDATED, From 0165a6f18ea4a0e0745ebb9966ae08a736642e32 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 23 Jan 2023 11:52:34 +0100 Subject: [PATCH 003/114] videoroom: map multistream "updating" event to "updated" --- src/plugins/videoroom-plugin.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index b0e6a30..6f4e925 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -364,6 +364,12 @@ class VideoRoomHandle extends Handle { janode_event.event = PLUGIN_EVENT.UPDATED; break; + /* [multistream] updating event, sent when janus receives another "update" before getting a JSEP answer for the previous one */ + case 'updating': + janode_event.data.streams = message_data.streams; + janode_event.event = PLUGIN_EVENT.UPDATED; + break; + /* Generic events (error, notifications ...) */ case 'event': /* VideoRoom Error */ @@ -1265,7 +1271,7 @@ class VideoRoomHandle extends Handle { * @property {object[]} publishers - The list of active publishers * @property {number|string} publishers[].feed - The feed of an active publisher * @property {string} publishers[].display - The display name of an active publisher - * @property {object[]} [publishers[].streams] - [multistream] streams description + * @property {object[]} [publishers[].streams] - [multistream] Streams description * @property {RTCSessionDescription} [jsep] - The JSEP answer */ @@ -1501,7 +1507,7 @@ export default { * @property {object[]} publishers - List of the new publishers * @property {number|string} publishers[].feed - Feed identifier of the new publisher * @property {string} publishers[].display - Display name of the new publisher - * @property {object[]} [publishers[].streams] - [multistream] streams description + * @property {object[]} [publishers[].streams] - [multistream] Streams description */ VIDEOROOM_PUB_LIST: PLUGIN_EVENT.PUB_LIST, From f0d40a05b1fbafcff45378f490d5ca00cdf3e1fe Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 23 Jan 2023 12:26:55 +0100 Subject: [PATCH 004/114] videoroom: add 0.x properties "audio_codec", "video_codec", "simulcast" and 1.x "autoupdate" --- src/plugins/videoroom-plugin.js | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 6f4e925..5a7d594 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -184,12 +184,16 @@ class VideoRoomHandle extends Handle { janode_event.data.feed = message_data.id; janode_event.data.description = message_data.description; janode_event.data.private_id = message_data.private_id; - janode_event.data.publishers = message_data.publishers.map(({ id, display, talking, streams }) => { + janode_event.data.publishers = message_data.publishers.map(({ id, display, talking, audio_codec, video_codec, simulcast, streams }) => { const pub = { feed: id, display, }; if (typeof talking !== 'undefined') pub.talking = talking; + if (typeof audio_codec !== 'undefined') pub.audiocodec = audio_codec; + if (typeof video_codec !== 'undefined') pub.videocodec = video_codec; + if (typeof simulcast !== 'undefined') pub.simulcast = simulcast; + // Multistream if (typeof streams !== 'undefined') pub.streams = streams; return pub; }); @@ -391,12 +395,16 @@ class VideoRoomHandle extends Handle { /* Publisher list notification */ if (message_data.publishers) { janode_event.event = PLUGIN_EVENT.PUB_LIST; - janode_event.data.publishers = message_data.publishers.map(({ id, display, talking, streams }) => { + janode_event.data.publishers = message_data.publishers.map(({ id, display, talking, audio_codec, video_codec, simulcast, streams }) => { const pub = { feed: id, display, }; if (typeof talking !== 'undefined') pub.talking = talking; + if (typeof audio_codec !== 'undefined') pub.audiocodec = audio_codec; + if (typeof video_codec !== 'undefined') pub.videocodec = video_codec; + if (typeof simulcast !== 'undefined') pub.simulcast = simulcast; + // Multistream if (typeof streams !== 'undefined') pub.streams = streams; return pub; }); @@ -778,10 +786,11 @@ class VideoRoomHandle extends Handle { * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled + * @param {boolean} [params.autoupdate] - [multistream] Whether a new SDP offer is sent automatically when a subscribed publisher leaves * @param {string} [params.token] - The optional token needed * @returns {Promise} */ - async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, token }) { + async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, autoupdate, token }) { const body = { request: REQUEST_JOIN, ptype: PTYPE_LISTENER, @@ -796,6 +805,8 @@ class VideoRoomHandle extends Handle { if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; + // Multistream + if (typeof autoupdate === 'boolean') body.autoupdate = autoupdate; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; @@ -1270,7 +1281,11 @@ class VideoRoomHandle extends Handle { * @property {number} private_id - The private id that can be used when subscribing * @property {object[]} publishers - The list of active publishers * @property {number|string} publishers[].feed - The feed of an active publisher - * @property {string} publishers[].display - The display name of an active publisher + * @property {string} [publishers[].display] - The display name of an active publisher + * @property {boolean} [publishers[].talking] - Whether the publisher is talking or not + * @property {string} [publishers[].audiocodec] - The audio codec used by active publisher + * @property {string} [publishers[].videocodec] - The video codec used by active publisher + * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) * @property {object[]} [publishers[].streams] - [multistream] Streams description * @property {RTCSessionDescription} [jsep] - The JSEP answer */ @@ -1292,7 +1307,7 @@ class VideoRoomHandle extends Handle { * @property {number|string} feed - The current published feed * @property {object[]} participants - The list of current participants * @property {number|string} participants[].feed - Feed identifier of the participant - * @property {string} [participants[].display] - The participant display name, if available + * @property {string} [participants[].display] - The participant's display name, if available * @property {boolean} participants[].publisher - Whether the user is an active publisher in the room * @property {boolean} [participants[].talking] - True if participant is talking */ @@ -1507,6 +1522,10 @@ export default { * @property {object[]} publishers - List of the new publishers * @property {number|string} publishers[].feed - Feed identifier of the new publisher * @property {string} publishers[].display - Display name of the new publisher + * @property {boolean} [publishers[].talking] - Whether the publisher is talking or not + * @property {string} [publishers[].audiocodec] - The audio codec used by active publisher + * @property {string} [publishers[].videocodec] - The video codec used by active publisher + * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) * @property {object[]} [publishers[].streams] - [multistream] Streams description */ VIDEOROOM_PUB_LIST: PLUGIN_EVENT.PUB_LIST, From 4e269c0430343e8786f7e60eb62a2efbc63ac05b Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 25 Jan 2023 15:27:09 +0100 Subject: [PATCH 005/114] videoroom: add end-to-end encryption signalling --- src/plugins/videoroom-plugin.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 5a7d594..36eeeca 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -132,6 +132,7 @@ class VideoRoomHandle extends Handle { /* Add JSEP data if available */ if (jsep) janode_event.data.jsep = jsep; + if (jsep && typeof jsep.e2ee === 'boolean') janode_event.data.e2ee = jsep.e2ee; /* Add room information if available */ if (room) janode_event.data.room = room; @@ -570,10 +571,11 @@ class VideoRoomHandle extends Handle { * @param {string} [params.pin] - The optional pin needed to join the room * @param {boolean} [params.record] - Enable the recording * @param {string} [params.filename] - If recording, the base path/file to use for the recording + * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection * @param {RTCSessionDescription} [params.jsep] - The JSEP offer * @returns {Promise} */ - async joinConfigurePublisher({ room, feed, audio, video, data, bitrate, record, filename, display, token, pin, jsep }) { + async joinConfigurePublisher({ room, feed, audio, video, data, bitrate, record, filename, display, token, pin, e2ee, jsep }) { const body = { request: REQUEST_JOIN_CONFIGURE, ptype: PTYPE_PUBLISHER, @@ -589,6 +591,7 @@ class VideoRoomHandle extends Handle { if (typeof filename === 'string') body.filename = filename; if (typeof token === 'string') body.token = token; if (typeof pin === 'string') body.pin = pin; + if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; const response = await this.message(body, jsep).catch(e => { /* Cleanup the WebRTC status in Janus in case of errors when publishing */ @@ -642,10 +645,11 @@ class VideoRoomHandle extends Handle { * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled (subscribers only) * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below (subscribers only) * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled (subscribers only) + * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection * @param {RTCSessionDescription} [params.jsep] - The JSEP offer (publishers only) * @returns {Promise} */ - async configure({ audio, video, data, bitrate, record, filename, display, restart, update, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, jsep }) { + async configure({ audio, video, data, bitrate, record, filename, display, restart, update, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, e2ee, jsep }) { const body = { request: REQUEST_CONFIGURE, }; @@ -661,6 +665,7 @@ class VideoRoomHandle extends Handle { if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; + if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; const response = await this.message(body, jsep).catch(e => { /* Cleanup the WebRTC status in Janus in case of errors when publishing */ @@ -706,10 +711,11 @@ class VideoRoomHandle extends Handle { * @param {number} [params.bitrate] - Bitrate cap * @param {boolean} [params.record] - True to record the feed * @param {string} [params.filename] - If recording, the base path/file to use for the recording + * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection * @param {RTCSessionDescription} params.jsep - The JSEP offer * @returns {Promise} */ - async publish({ audio, video, data, bitrate, record, filename, display, jsep }) { + async publish({ audio, video, data, bitrate, record, filename, display, e2ee, jsep }) { if (typeof jsep === 'object' && jsep && jsep.type !== 'offer') { const error = new Error('jsep must be an offer'); return Promise.reject(error); @@ -724,6 +730,7 @@ class VideoRoomHandle extends Handle { if (typeof record === 'boolean') body.record = record; if (typeof filename === 'string') body.filename = filename; if (typeof display === 'string') body.display = display; + if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; const response = await this.message(body, jsep).catch(e => { /* Cleanup the WebRTC status in Janus in case of errors when publishing */ @@ -1073,7 +1080,8 @@ class VideoRoomHandle extends Handle { * @param {boolean} [params.talking_events] - True to enable talking events * @param {number} [params.talking_level_threshold] - Audio level threshold for talking events in the range [0, 127] * @param {number} [params.talking_packets_threshold] - Audio packets threshold for talking events - * @param {boolean} [params.require_pvtid] - whether subscriptions are required to provide a valid private_id + * @param {boolean} [params.require_pvtid] - Whether subscriptions are required to provide a valid private_id + * @param {boolean} [params.require_e2ee] - Whether all participants are required to publish and subscribe using e2e encryption * @param {boolean} [params.record] - Wheter to enable recording of any publisher * @param {string} [params.rec_dir] - Folder where recordings should be stored * @param {boolean} [params.videoorient] - Whether the video-orientation RTP extension must be negotiated @@ -1082,7 +1090,7 @@ class VideoRoomHandle extends Handle { */ async create({ room, description, max_publishers, permanent, is_private, secret, pin, bitrate, bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, - require_pvtid, record, rec_dir, videoorient, h264_profile }) { + require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile }) { const body = { request: REQUEST_CREATE, }; @@ -1102,6 +1110,7 @@ class VideoRoomHandle extends Handle { if (typeof talking_level_threshold === 'number' && talking_level_threshold >= 0 && talking_level_threshold <= 127) body.audio_level_average = talking_level_threshold; if (typeof talking_packets_threshold === 'number' && talking_packets_threshold > 0) body.audio_active_packets = talking_packets_threshold; if (typeof require_pvtid === 'boolean') body.require_pvtid = require_pvtid; + if (typeof require_e2ee === 'boolean') body.require_e2ee = require_e2ee; if (typeof record === 'boolean') body.record = record; if (typeof rec_dir === 'string') body.rec_dir = rec_dir; if (typeof videoorient === 'boolean') body.videoorient_ext = videoorient; From 479396e4f62652b99c08b2d84470d6b1159b1ef6 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 6 Feb 2023 14:24:31 +0100 Subject: [PATCH 006/114] version: bump to v1.6.7 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index cce6f76..15b37db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.6.6", + "version": "1.6.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "janode", - "version": "1.6.6", + "version": "1.6.7", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index 0902f2e..1883a88 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.6.6", + "version": "1.6.7", "type": "module", "keywords": [ "janus", From 0344e8a78f0e875b5af60c4233d9c7493d856103 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 3 Jul 2023 15:51:01 +0200 Subject: [PATCH 007/114] gitignore: update --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3cd189d..ad7cb48 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules build out +.vscode config.js bundle.js From fd9b32d6e05f61adcdaaff9ac3db93079a7d4bbb Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 1 Sep 2023 12:30:39 +0200 Subject: [PATCH 008/114] Support suspended join. Add docs. --- .../audiobridge/html/audiobridge-client.js | 3 +- src/plugins/audiobridge-plugin.js | 67 ++++++++++++++++++- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/examples/audiobridge/html/audiobridge-client.js b/examples/audiobridge/html/audiobridge-client.js index 9320115..c082f4c 100644 --- a/examples/audiobridge/html/audiobridge-client.js +++ b/examples/audiobridge/html/audiobridge-client.js @@ -51,11 +51,12 @@ const socket = io({ reconnection: false, }); -function join({ room = myRoom, display = myName, muted = false, token = null, rtp_participant = null, group = null } = {}) { +function join({ room = myRoom, display = myName, muted = false, suspended = false, token = null, rtp_participant = null, group = null } = {}) { const joinData = { room, display, muted, + suspended, token, rtp_participant, group, diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index c6023d8..d4c0822 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -380,12 +380,13 @@ class AudioBridgeHandle extends Handle { * @param {number} [params.volume] - The percent volume * @param {boolean} [params.record] - True to enable recording * @param {string} [params.filename] - The recording filename + * @param {boolean} [params.suspended] - True to join in suspended status * @param {module:audiobridge-plugin~RtpParticipant} [params.rtp_participant] - Set a descriptor object if you need a RTP participant * @param {string} [params.group] - The group to assign to this participant * @param {boolean} [params.generate_offer] - True to get Janus to send the SDP offer. * @returns {Promise} */ - async join({ room, feed, display, muted, pin, token, quality, volume, record, filename, rtp_participant, group, generate_offer }) { + async join({ room, feed, display, muted, pin, token, quality, volume, record, filename, suspended, rtp_participant, group, generate_offer }) { const body = { request: REQUEST_JOIN, room, @@ -399,6 +400,7 @@ class AudioBridgeHandle extends Handle { if (typeof volume === 'number') body.volume = volume; if (typeof record === 'boolean') body.record = record; if (typeof filename === 'string') body.filename = filename; + if (typeof suspended === 'boolean') body.suspended = suspended; if (typeof rtp_participant === 'object' && rtp_participant) body.rtp = rtp_participant; if (typeof group === 'string') body.group = group; if (typeof generate_offer === 'boolean') body.generate_offer = generate_offer; @@ -872,6 +874,16 @@ class AudioBridgeHandle extends Handle { throw (error); } + /** + * Suspend an audiobridge participant. + * + * @param {object} params + * @param {number|string} params.room - The involved room + * @param {number|string} params.feed - The feed id to be suspended + * @param {boolean} [params.stop_record] - Whether the recording of this participant should be stopped too + * @param {string} [params.secret] - The optional secret needed to manage the room + * @returns {Promise} + */ async suspend({ room, feed, stop_record, secret }) { const body = { request: REQUEST_SUSPEND_PARTICIPANT, @@ -883,12 +895,25 @@ class AudioBridgeHandle extends Handle { const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.SUCCESS) + if (event === PLUGIN_EVENT.SUCCESS) { + evtdata.feed = feed; return evtdata; + } const error = new Error(`unexpected response to ${body.request} request`); throw (error); } + /** + * Resume an audiobridge participant after a suspend. + * + * @param {object} params + * @param {number|string} params.room - The involved room + * @param {number|string} params.feed - The feed id to be resumed + * @param {boolean} [params.record] - Whether to start recording this resumed feed + * @param {string} [params.filename] - The recording filename + * @param {string} [params.secret] - The optional secret needed to manage the room + * @returns {Promise} + */ async resume({ room, feed, record, filename, secret }) { const body = { request: REQUEST_RESUME_PARTICIPANT, @@ -901,8 +926,10 @@ class AudioBridgeHandle extends Handle { const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.SUCCESS) + if (event === PLUGIN_EVENT.SUCCESS) { + evtdata.feed = feed; return evtdata; + } const error = new Error(`unexpected response to ${body.request} request`); throw (error); } @@ -1069,6 +1096,22 @@ class AudioBridgeHandle extends Handle { * @property {number|string} room - The involved room */ +/** + * The response event for audiobridge suspend request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_SUSPEND_RESPONSE + * @property {number|string} room - The involved room + * @property {number|string} feed - The involved feed id + */ + +/** + * The response event for audiobridge resume request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_RESUME_RESPONSE + * @property {number|string} room - The involved room + * @property {number|string} feed - The involved feed id + */ + /** * The response event for audiobridge ACL token edit request. * @@ -1092,6 +1135,8 @@ class AudioBridgeHandle extends Handle { * @property {string} EVENT.AUDIOBRIDGE_PEER_LEAVING {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_LEAVING} * @property {string} EVENT.AUDIOBRIDGE_TALKING {@link module:audiobridge-plugin~AUDIOBRIDGE_TALKING} * @property {string} EVENT.AUDIOBRIDGE_PEER_TALKING {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_TALKING} + * @property {string} EVENT.AUDIOBRIDGE_PEER_SUSPENDED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_SUSPENDED} + * @property {string} EVENT.AUDIOBRIDGE_PEER_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_RESUMED} * @property {string} EVENT.AUDIOBRIDGE_ROOM_MUTED {@link module:audiobridge-plugin~AUDIOBRIDGE_ROOM_MUTED} * @property {string} EVENT.AUDIOBRIDGE_ERROR {@link module:audiobridge-plugin~AUDIOBRIDGE_ERROR} */ @@ -1186,8 +1231,24 @@ export default { */ AUDIOBRIDGE_PEER_TALKING: PLUGIN_EVENT.PEER_TALKING, + /** + * Notify if a participant has been suspended. + * + * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_SUSPENDED + * @type {object} + * @property {number|string} room + * @property {number|string} feed + */ AUDIOBRIDGE_PEER_SUSPENDED: PLUGIN_EVENT.PEER_SUSPENDED, + /** + * Notify if a participant has been resumed. + * + * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_RESUMED + * @type {object} + * @property {number|string} room + * @property {number|string} feed + */ AUDIOBRIDGE_PEER_RESUMED: PLUGIN_EVENT.PEER_RESUMED, /** From e0fca56fc18ea53f2d55ad53953c9ef388f4b4ac Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 4 Sep 2023 11:35:25 +0200 Subject: [PATCH 009/114] Support pause_events --- src/plugins/audiobridge-plugin.js | 23 +- src/plugins/videoroom-ms-plugin.js | 1638 ++++++++++++++++++++++++++++ 2 files changed, 1659 insertions(+), 2 deletions(-) create mode 100644 src/plugins/videoroom-ms-plugin.js diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index d4c0822..723a6f6 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -341,9 +341,24 @@ class AudioBridgeHandle extends Handle { /* A participant has been resumed */ if (typeof message_data.resumed != 'undefined') { janode_event.data.feed = message_data.resumed; + if (message_data.participants) { + /* Add participants data */ + janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking, suspended }) => { + const peer = { + feed: id, + display, + muted, + setup, + }; + if (typeof talking !== 'undefined') peer.talking = talking; + if (typeof suspended !== 'undefined') peer.suspended = suspended; + return peer; + }); + } janode_event.event = PLUGIN_EVENT.PEER_RESUMED; break; } + } /* The event has been handled */ @@ -381,12 +396,13 @@ class AudioBridgeHandle extends Handle { * @param {boolean} [params.record] - True to enable recording * @param {string} [params.filename] - The recording filename * @param {boolean} [params.suspended] - True to join in suspended status + * @param {boolean} [params.pause_events] - Wheter to pause notification events for suspended participants * @param {module:audiobridge-plugin~RtpParticipant} [params.rtp_participant] - Set a descriptor object if you need a RTP participant * @param {string} [params.group] - The group to assign to this participant * @param {boolean} [params.generate_offer] - True to get Janus to send the SDP offer. * @returns {Promise} */ - async join({ room, feed, display, muted, pin, token, quality, volume, record, filename, suspended, rtp_participant, group, generate_offer }) { + async join({ room, feed, display, muted, pin, token, quality, volume, record, filename, suspended, pause_events, rtp_participant, group, generate_offer }) { const body = { request: REQUEST_JOIN, room, @@ -401,6 +417,7 @@ class AudioBridgeHandle extends Handle { if (typeof record === 'boolean') body.record = record; if (typeof filename === 'string') body.filename = filename; if (typeof suspended === 'boolean') body.suspended = suspended; + if (typeof pause_events === 'boolean') body.pause_events = pause_events; if (typeof rtp_participant === 'object' && rtp_participant) body.rtp = rtp_participant; if (typeof group === 'string') body.group = group; if (typeof generate_offer === 'boolean') body.generate_offer = generate_offer; @@ -881,16 +898,18 @@ class AudioBridgeHandle extends Handle { * @param {number|string} params.room - The involved room * @param {number|string} params.feed - The feed id to be suspended * @param {boolean} [params.stop_record] - Whether the recording of this participant should be stopped too + * @param {boolean} [params.pause_events] - Wheter to pause notification events for suspended participants * @param {string} [params.secret] - The optional secret needed to manage the room * @returns {Promise} */ - async suspend({ room, feed, stop_record, secret }) { + async suspend({ room, feed, stop_record, pause_events, secret }) { const body = { request: REQUEST_SUSPEND_PARTICIPANT, room, id: feed }; if (typeof stop_record === 'boolean') body.stop_record = stop_record; + if (typeof pause_events === 'boolean') body.pause_events = pause_events; if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); diff --git a/src/plugins/videoroom-ms-plugin.js b/src/plugins/videoroom-ms-plugin.js new file mode 100644 index 0000000..eebbc61 --- /dev/null +++ b/src/plugins/videoroom-ms-plugin.js @@ -0,0 +1,1638 @@ +'use strict'; + +/** + * This module contains the implementation of the VideoRoom multistream plugin (ref. {@link https://janus.conf.meetecho.com/docs/videoroom.html}). + * @module videoroom-ms-plugin + */ + +import Handle from '../handle.js'; + +/* The plugin ID exported in the plugin descriptor */ +const PLUGIN_ID = 'janus.plugin.videoroom-ms'; + +/* These are the requests defined for the Janus VideoRoom API */ +const REQUEST_JOIN = 'join'; +const REQUEST_CONFIGURE = 'configure'; +const REQUEST_JOIN_CONFIGURE = 'joinandconfigure'; +const REQUEST_LIST_PARTICIPANTS = 'listparticipants'; +const REQUEST_ENABLE_RECORDING = 'enable_recording'; +const REQUEST_KICK = 'kick'; +const REQUEST_START = 'start'; +const REQUEST_PAUSE = 'pause'; +const REQUEST_SWITCH = 'switch'; +const REQUEST_PUBLISH = 'publish'; +const REQUEST_UNPUBLISH = 'unpublish'; +const REQUEST_LEAVE = 'leave'; +const REQUEST_UPDATE = 'update'; + +const REQUEST_EXISTS = 'exists'; +const REQUEST_LIST_ROOMS = 'list'; +const REQUEST_CREATE = 'create'; +const REQUEST_DESTROY = 'destroy'; +const REQUEST_ALLOW = 'allowed'; + +const REQUEST_RTP_FWD_START = 'rtp_forward'; +const REQUEST_RTP_FWD_STOP = 'stop_rtp_forward'; +const REQUEST_RTP_FWD_LIST = 'listforwarders'; + +const PTYPE_PUBLISHER = 'publisher'; +const PTYPE_LISTENER = 'subscriber'; + +/* These are the events/responses that the Janode plugin will manage */ +/* Some of them will be exported in the plugin descriptor */ +const PLUGIN_EVENT = { + PUB_JOINED: 'videoroom_joined', + SUB_JOINED: 'videoroom_subscribed', + PUB_LIST: 'videoroom_publisher_list', + PARTICIPANTS_LIST: 'videoroom_participants_list', + PUB_PEER_JOINED: 'videoroom_publisher_joined', + STARTED: 'videoroom_started', + PAUSED: 'videoroom_paused', + SWITCHED: 'videoroom_switched', + CONFIGURED: 'videoroom_configured', + SLOW_LINK: 'videoroom_slowlink', + DISPLAY: 'videoroom_display', + UNPUBLISHED: 'videoroom_unpublished', + LEAVING: 'videoroom_leaving', + UPDATED: 'videoroom_updated', + KICKED: 'videoroom_kicked', + RECORDING_ENABLED_STATE: 'videoroom_recording_enabled_state', + TALKING: 'videoroom_talking', + SC_SUBSTREAM_LAYER: 'videoroom_sc_substream_layer', + SC_TEMPORAL_LAYERS: 'videoroom_sc_temporal_layers', + ALLOWED: 'videoroom_allowed', + EXISTS: 'videoroom_exists', + ROOMS_LIST: 'videoroom_list', + CREATED: 'videoroom_created', + DESTROYED: 'videoroom_destroyed', + RTP_FWD_STARTED: 'videoroom_rtp_fwd_started', + RTP_FWD_STOPPED: 'videoroom_rtp_fwd_stopped', + RTP_FWD_LIST: 'videoroom_rtp_fwd_list', + SUCCESS: 'videoroom_success', + ERROR: 'videoroom_error', +}; + +/** + * The class implementing the VideoRoom plugin (ref. {@link https://janus.conf.meetecho.com/docs/videoroom.html}).
+ * + * It extends the base Janode Handle class and overrides the "handleMessage" method.
+ * + * Moreover it defines many methods to support VideoRoom operations.
+ * + * @hideconstructor + */ +class VideoRoomHandle extends Handle { + /** + * Create a Janode VideoRoom handle. + * + * @param {module:session~Session} session - A reference to the parent session + * @param {number} id - The handle identifier + */ + constructor(session, id) { + super(session, id); + + /** + * Either the feed identifier assigned to this publisher handle or the publisher's feed in case this handle is a subscriber. + * + * @type {number|string} + */ + this.feed = null; + + /** + * The identifier of the videoroom the handle has joined. + * + * @type {number|string} + */ + this.room = null; + } + + /** + * The custom "handleMessage" needed for handling VideoRoom messages. + * + * @private + * @param {object} janus_message + * @returns {object} A falsy value for unhandled events, a truthy value for handled events + */ + handleMessage(janus_message) { + const { plugindata, jsep, transaction } = janus_message; + if (plugindata && plugindata.data && plugindata.data.videoroom) { + /** + * @type {VideoRoomData} + */ + const message_data = plugindata.data; + const { videoroom, error, error_code, room } = message_data; + + /* Prepare an object for the output Janode event */ + const janode_event = { + /* The name of the resolved event */ + event: null, + /* The event payload */ + data: {}, + }; + + /* Add JSEP data if available */ + if (jsep) janode_event.data.jsep = jsep; + if (jsep && typeof jsep.e2ee === 'boolean') janode_event.data.e2ee = jsep.e2ee; + /* Add room information if available */ + if (room) janode_event.data.room = room; + + /* The plugin will emit an event only if the handle does not own the transaction */ + /* That means that a transaction has already been closed or this is an async event */ + const emit = (this.ownsTransaction(transaction) === false); + + /* Use the "janode" property to store the output event */ + janus_message._janode = janode_event; + + switch (videoroom) { + + /* Success response */ + case 'success': + /* Room exists API */ + if (typeof message_data.exists !== 'undefined') { + janode_event.data.exists = message_data.exists; + janode_event.event = PLUGIN_EVENT.EXISTS; + break; + } + /* Room list API */ + if (typeof message_data.list !== 'undefined') { + janode_event.data.list = message_data.list; + janode_event.event = PLUGIN_EVENT.ROOMS_LIST; + break; + } + /* Tokens management (add/remove/enable) */ + if (typeof message_data.allowed !== 'undefined') { + janode_event.data.list = message_data.allowed; + janode_event.event = PLUGIN_EVENT.ALLOWED; + break; + } + /* Global recording enabled or disabled */ + if (typeof message_data.record !== 'undefined') { + janode_event.data.record = message_data.record; + janode_event.event = PLUGIN_EVENT.RECORDING_ENABLED_STATE; + break; + } + + /* Generic success event */ + janode_event.event = PLUGIN_EVENT.SUCCESS; + break; + + /* Publisher joined */ + case 'joined': + /* Store room and feed id */ + this.room = room; + this.feed = message_data.id; + + janode_event.data.feed = message_data.id; + janode_event.data.description = message_data.description; + janode_event.data.private_id = message_data.private_id; + janode_event.data.publishers = message_data.publishers.map(({ id, display, streams }) => { + const pub = { + feed: id, + display, + }; + pub.streams = streams; + return pub; + }); + janode_event.event = PLUGIN_EVENT.PUB_JOINED; + break; + + /* Subscriber joined */ + case 'attached': + /* Store room and feed id */ + this.room = room; + this.feed = message_data.id; + + janode_event.data.feed = message_data.id; + janode_event.data.display = message_data.display; + janode_event.event = PLUGIN_EVENT.SUB_JOINED; + break; + + /* Slow-link event */ + case 'slow_link': + janode_event.data.feed = this.feed; + janode_event.data.bitrate = message_data['current-bitrate']; + janode_event.event = PLUGIN_EVENT.SLOW_LINK; + break; + + /* Participants list */ + case 'participants': + janode_event.data.participants = message_data.participants.map(({ id, display, publisher, talking }) => { + const peer = { + feed: id, + display, + publisher, + }; + if (typeof talking !== 'undefined') peer.talking = talking; + return peer; + }); + janode_event.event = PLUGIN_EVENT.PARTICIPANTS_LIST; + break; + + /* Room created */ + case 'created': + janode_event.event = PLUGIN_EVENT.CREATED; + janode_event.data.permanent = message_data.permanent; + break; + + /* Room destroyed */ + case 'destroyed': + janode_event.event = PLUGIN_EVENT.DESTROYED; + break; + + /* RTP forwarding started */ + case 'rtp_forward': + janode_event.data.feed = message_data.publisher_id; + janode_event.data.forwarder = { + host: message_data.rtp_stream.host, + }; + if (message_data.rtp_stream.audio) { + janode_event.data.forwarder.audio_port = message_data.rtp_stream.audio; + janode_event.data.forwarder.audio_rtcp_port = message_data.rtp_stream.audio_rtcp; + janode_event.data.forwarder.audio_stream = message_data.rtp_stream.audio_stream_id; + } + if (message_data.rtp_stream.video) { + janode_event.data.forwarder.video_port = message_data.rtp_stream.video; + janode_event.data.forwarder.video_rtcp_port = message_data.rtp_stream.video_rtcp; + janode_event.data.forwarder.video_stream = message_data.rtp_stream.video_stream_id; + } + if (message_data.rtp_stream.data) { + janode_event.data.forwarder.data_port = message_data.rtp_stream.data; + janode_event.data.forwarder.data_stream = message_data.rtp_stream.data_stream_id; + } + janode_event.event = PLUGIN_EVENT.RTP_FWD_STARTED; + break; + + /* RTP forwarding stopped */ + case 'stop_rtp_forward': + janode_event.data.feed = message_data.publisher_id; + janode_event.data.stream = message_data.stream_id; + janode_event.event = PLUGIN_EVENT.RTP_FWD_STOPPED; + break; + + /* RTP forwarders list */ + case 'forwarders': + if (janode_event.data.forwarders) { + janode_event.data.forwarders = message_data.rtp_forwarders.map(({ publisher_id, rtp_forwarder }) => { + const pub = { + feed: publisher_id, + }; + + pub.forwarders = rtp_forwarder.map(forw => { + const forwarder = { + host: forw.ip, + }; + + if (forw.audio_stream_id) { + forwarder.audio_port = forw.port; + forwarder.audio_rtcp_port = forw.remote_rtcp_port; + forwarder.audio_stream = forw.audio_stream_id; + } + if (forw.video_stream_id) { + forwarder.video_port = forw.port; + forwarder.video_rtcp_port = forw.remote_rtcp_port; + forwarder.video_stream = forw.video_stream_id; + } + if (forw.data_stream_id) { + forwarder.data_port = forw.port; + forwarder.data_stream = forw.data_stream_id; + } + + return forwarder; + }); + + return pub; + }); + } + else if (janode_event.data.publishers) { + janode_event.data.forwarders = message_data.publishers.map(({ publisher_id, forwarders }) => { + const pub = { + feed: publisher_id, + }; + + pub.forwarders = forwarders.map(forw => { + const forwarder = { + host: forw.host, + }; + + if (forw.type === 'audio') { + forwarder.audio_port = forw.port; + forwarder.audio_rtcp_port = forw.remote_rtcp_port; + forwarder.audio_stream = forw.stream_id; + } + if (forw.type === 'video') { + forwarder.video_port = forw.port; + forwarder.video_rtcp_port = forw.remote_rtcp_port; + forwarder.video_stream = forw.stream_id; + if (typeof forw.substream !== 'undefined') { + forwarder.sc_substream_layer = forw.substream; + } + } + if (forw.type === 'data') { + forwarder.data_port = forw.port; + forwarder.data_stream = forw.stream_id; + } + + if (typeof forw.ssrc !== 'undefined') + forwarder.ssrc = forw.ssrc; + if (typeof forw.pt !== 'undefined') + forwarder.pt = forw.pt; + if (typeof forw.srtp !== 'undefined') + forwarder.srtp = forw.srtp; + + return forwarder; + }); + + return pub; + }); + } + + janode_event.event = PLUGIN_EVENT.RTP_FWD_LIST; + break; + + /* Talking events */ + case 'talking': + case 'stopped-talking': + janode_event.data.feed = message_data.id; + janode_event.data.talking = (videoroom === 'talking'); + janode_event.data.audio_level = message_data['audio-level-dBov-avg']; + janode_event.event = PLUGIN_EVENT.TALKING; + break; + + /* [multistream] updated event */ + case 'updated': + janode_event.data.streams = message_data.streams; + janode_event.event = PLUGIN_EVENT.UPDATED; + break; + + /* [multistream] updating event, sent when janus receives another "update" before getting a JSEP answer for the previous one */ + case 'updating': + janode_event.data.streams = message_data.streams; + janode_event.event = PLUGIN_EVENT.UPDATED; + break; + + /* Generic events (error, notifications ...) */ + case 'event': + /* VideoRoom Error */ + if (error) { + janode_event.event = PLUGIN_EVENT.ERROR; + janode_event.data = new Error(`${error_code} ${error}`); + janode_event.data._code = error_code; + /* In case of error, close a transaction */ + this.closeTransactionWithError(transaction, janode_event.data); + break; + } + /* Participant joined notification (notify_joining) */ + if (message_data.joining) { + janode_event.event = PLUGIN_EVENT.PUB_PEER_JOINED; + janode_event.data.feed = message_data.joining.id; + if (message_data.joining.display) janode_event.data.display = message_data.joining.display; + break; + } + /* Publisher list notification */ + if (message_data.publishers) { + janode_event.event = PLUGIN_EVENT.PUB_LIST; + janode_event.data.publishers = message_data.publishers.map(({ id, display, talking, audio_codec, video_codec, simulcast, streams }) => { + const pub = { + feed: id, + display, + }; + if (typeof talking !== 'undefined') pub.talking = talking; + if (typeof audio_codec !== 'undefined') pub.audiocodec = audio_codec; + if (typeof video_codec !== 'undefined') pub.videocodec = video_codec; + if (typeof simulcast !== 'undefined') pub.simulcast = simulcast; + // Multistream + if (typeof streams !== 'undefined') pub.streams = streams; + return pub; + }); + break; + } + /* Configuration events (publishing, general configuration) */ + if (typeof message_data.configured !== 'undefined') { + janode_event.event = PLUGIN_EVENT.CONFIGURED; + janode_event.data.feed = this.feed; + janode_event.data.configured = message_data.configured; + break; + } + /* Display name changed event */ + if (typeof message_data.display !== 'undefined' && typeof message_data.switched === 'undefined') { + janode_event.event = PLUGIN_EVENT.DISPLAY; + janode_event.data.feed = message_data.id; + janode_event.data.display = message_data.display; + break; + } + /* Subscribed feed started */ + if (typeof message_data.started !== 'undefined') { + janode_event.event = PLUGIN_EVENT.STARTED; + janode_event.data.feed = this.feed; + janode_event.data.started = message_data.started; + break; + } + /* Subscribed feed paused */ + if (typeof message_data.paused !== 'undefined') { + janode_event.event = PLUGIN_EVENT.PAUSED; + janode_event.data.feed = this.feed; + janode_event.data.paused = message_data.paused; + break; + } + /* Subscribed feed switched */ + if (typeof message_data.switched !== 'undefined') { + janode_event.event = PLUGIN_EVENT.SWITCHED; + janode_event.data.switched = message_data.switched; + if (message_data.switched === 'ok' && typeof message_data.id !== 'undefined') { + janode_event.data.from_feed = this.feed; + this.feed = message_data.id; + janode_event.data.to_feed = this.feed; + janode_event.data.display = message_data.display; + } + break; + } + /* Unpublished own or other feed */ + if (typeof message_data.unpublished !== 'undefined') { + janode_event.event = PLUGIN_EVENT.UNPUBLISHED; + janode_event.data.feed = (message_data.unpublished === 'ok') ? this.feed : message_data.unpublished; + break; + } + /* Leaving confirmation */ + if (typeof message_data.leaving !== 'undefined') { + janode_event.event = PLUGIN_EVENT.LEAVING; + janode_event.data.feed = (message_data.leaving === 'ok') ? this.feed : message_data.leaving; + if (message_data.reason) janode_event.data.reason = message_data.reason; + break; + } + /* Participant kicked out */ + if (typeof message_data.kicked !== 'undefined') { + janode_event.event = PLUGIN_EVENT.KICKED; + janode_event.data.feed = message_data.kicked; + break; + } + /* Participant left (for subscribers "leave") */ + if (typeof message_data.left !== 'undefined') { + janode_event.event = PLUGIN_EVENT.LEAVING; + janode_event.data.feed = this.feed; + break; + } + /* Simulcast substream layer switch */ + if (typeof message_data.substream !== 'undefined') { + janode_event.event = PLUGIN_EVENT.SC_SUBSTREAM_LAYER; + janode_event.data.feed = this.feed; + janode_event.data.sc_substream_layer = message_data.substream; + break; + } + /* Simulcast temporal layers switch */ + if (typeof message_data.temporal !== 'undefined') { + janode_event.event = PLUGIN_EVENT.SC_TEMPORAL_LAYERS; + janode_event.data.feed = this.feed; + janode_event.data.sc_temporal_layers = message_data.temporal; + break; + } + } + + /* The event has been handled */ + if (janode_event.event) { + /* Try to close the transaction */ + this.closeTransactionWithSuccess(transaction, janus_message); + /* If the transaction was not owned, emit the event */ + if (emit) this.emit(janode_event.event, janode_event.data); + return janode_event; + } + } + + /* The event has not been handled, return a falsy value */ + return null; + } + + /*----------*/ + /* USER API */ + /*----------*/ + + /* These are the APIs that users need to work with the videoroom plugin */ + + /** + * Join a videoroom as publisher. + * + * @param {object} params + * @param {number|string} params.room - The room to join to + * @param {number|string} [params.feed] - The feed identifier to use, if missing it is picked by Janus + * @param {string} [params.display] - The display name to use + * @param {string} [params.token] - The optional token needed to join the room + * @param {string} [params.pin] - The optional pin needed to join the room + * @returns {Promise} + */ + async joinPublisher({ room, feed, display, token, pin }) { + const body = { + request: REQUEST_JOIN, + ptype: PTYPE_PUBLISHER, + room, + }; + if (typeof feed === 'string' || typeof feed === 'number') body.id = feed; + if (typeof display === 'string') body.display = display; + if (typeof token === 'string') body.token = token; + if (typeof pin === 'string') body.pin = pin; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.PUB_JOINED) { + if (body.display) evtdata.display = body.display; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Join and configure videoroom handle as publisher. + * + * @param {object} params + * @param {number|string} params.room - The room to join to + * @param {number|string} [params.feed] - The feed identifier to use, if missing it is picked by Janus + * @param {object[]} params.streams + * @param {string} [params.display] - The display name to use + * @param {string} [params.token] - The optional token needed to join the room + * @param {string} [params.pin] - The optional pin needed to join the room + * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection + * @param {RTCSessionDescription} [params.jsep] - The JSEP offer + * @returns {Promise} + */ + async joinConfigurePublisher({ room, feed, streams, bitrate, record, filename, display, token, pin, e2ee, jsep }) { + const body = { + request: REQUEST_JOIN_CONFIGURE, + ptype: PTYPE_PUBLISHER, + room, + }; + if (typeof feed === 'string' || typeof feed === 'number') body.id = feed; + if (typeof display === 'string') body.display = display; + if (Array.isArray(streams)) body.streams = streams; + if (typeof bitrate === 'number') body.bitrate = bitrate; + if (typeof record === 'boolean') body.record = record; + if (typeof filename === 'string') body.filename = filename; + if (typeof token === 'string') body.token = token; + if (typeof pin === 'string') body.pin = pin; + if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; + + const response = await this.message(body, jsep).catch(e => { + /* Cleanup the WebRTC status in Janus in case of errors when publishing */ + /* + * + * JANUS_VIDEOROOM_ERROR_NO_SUCH_FEED 428 + * JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT 429 + * JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT 430 + * JANUS_VIDEOROOM_ERROR_INVALID_SDP_TYPE 431 + * JANUS_VIDEOROOM_ERROR_PUBLISHERS_FULL 432 + * JANUS_VIDEOROOM_ERROR_UNAUTHORIZED 433 + * JANUS_VIDEOROOM_ERROR_ALREADY_PUBLISHED 434 + * JANUS_VIDEOROOM_ERROR_NOT_PUBLISHED 435 + * JANUS_VIDEOROOM_ERROR_ID_EXISTS 436 + * JANUS_VIDEOROOM_ERROR_INVALID_SDP 437 + * + */ + if (jsep && e._code && e._code >= 429 && e._code <= 437 && e._code != 434) + this.hangup().catch(() => { }); + throw e; + }); + + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.PUB_JOINED) { + if (body.display) evtdata.display = body.display; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Configure a publisher or subscriber handle.
+ * Room is detected from the context since a handle must have joined before.
+ * Can also be used by publishers to publish a feed.
+ * + * Use this API also to trigger ICE restarts. Publishers can omit the + * restart/update flags, while subscribers need to use them to force + * the operation. + * + * @param {object} params + * @param {boolean} [params.audio] - True to request audio relaying + * @param {boolean} [params.video] - True to request video relaying + * @param {boolean} [params.data] - True to request datachannel relaying + * @param {string} [params.display] - The display name to use (publishers only) + * @param {number} [params.bitrate] - Bitrate cap (publishers only) + * @param {boolean} [params.record] - True to record the feed (publishers only) + * @param {string} [params.filename] - If recording, the base path/file to use for the recording (publishers only) + * @param {boolean} [params.restart] - Set to force a ICE restart + * @param {boolean} [params.update] - Set to force a renegotiation + * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled (subscribers only) + * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below (subscribers only) + * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled (subscribers only) + * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection + * @param {RTCSessionDescription} [params.jsep] - The JSEP offer (publishers only) + * @returns {Promise} + */ + async configure({ audio, video, data, bitrate, record, filename, display, restart, update, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, e2ee, jsep }) { + const body = { + request: REQUEST_CONFIGURE, + }; + if (typeof audio === 'boolean') body.audio = audio; + if (typeof video === 'boolean') body.video = video; + if (typeof data === 'boolean') body.data = data; + if (typeof bitrate === 'number') body.bitrate = bitrate; + if (typeof record === 'boolean') body.record = record; + if (typeof filename === 'string') body.filename = filename; + if (typeof display === 'string') body.display = display; + if (typeof restart === 'boolean') body.restart = restart; + if (typeof update === 'boolean') body.update = update; + if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; + if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; + if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; + if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; + + const response = await this.message(body, jsep).catch(e => { + /* Cleanup the WebRTC status in Janus in case of errors when publishing */ + /* + * + * JANUS_VIDEOROOM_ERROR_NO_SUCH_FEED 428 + * JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT 429 + * JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT 430 + * JANUS_VIDEOROOM_ERROR_INVALID_SDP_TYPE 431 + * JANUS_VIDEOROOM_ERROR_PUBLISHERS_FULL 432 + * JANUS_VIDEOROOM_ERROR_UNAUTHORIZED 433 + * JANUS_VIDEOROOM_ERROR_ALREADY_PUBLISHED 434 + * JANUS_VIDEOROOM_ERROR_NOT_PUBLISHED 435 + * JANUS_VIDEOROOM_ERROR_ID_EXISTS 436 + * JANUS_VIDEOROOM_ERROR_INVALID_SDP 437 + * + */ + if (jsep && e._code && e._code >= 429 && e._code <= 437 && e._code != 434) + this.hangup().catch(() => { }); + throw e; + }); + + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.CONFIGURED && evtdata.configured === 'ok') { + if (body.display) evtdata.display = body.display; + if (typeof body.request === 'boolean') evtdata.restart = body.restart; + if (typeof body.update === 'boolean') evtdata.update = body.update; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Publish a feed in the room. + * Room is detected from the context since a handle must have joined before. + * + * @param {object} params + * @param {boolean} [params.audio] - True to request audio relaying + * @param {boolean} [params.video] - True to request video relaying + * @param {boolean} [params.data] - True to request datachannel relaying + * @param {string} [params.display] - The display name to use + * @param {number} [params.bitrate] - Bitrate cap + * @param {boolean} [params.record] - True to record the feed + * @param {string} [params.filename] - If recording, the base path/file to use for the recording + * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection + * @param {RTCSessionDescription} params.jsep - The JSEP offer + * @returns {Promise} + */ + async publish({ audio, video, data, bitrate, record, filename, display, e2ee, jsep }) { + if (typeof jsep === 'object' && jsep && jsep.type !== 'offer') { + const error = new Error('jsep must be an offer'); + return Promise.reject(error); + } + const body = { + request: REQUEST_PUBLISH, + }; + if (typeof audio === 'boolean') body.audio = audio; + if (typeof video === 'boolean') body.video = video; + if (typeof data === 'boolean') body.data = data; + if (typeof bitrate === 'number') body.bitrate = bitrate; + if (typeof record === 'boolean') body.record = record; + if (typeof filename === 'string') body.filename = filename; + if (typeof display === 'string') body.display = display; + if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; + + const response = await this.message(body, jsep).catch(e => { + /* Cleanup the WebRTC status in Janus in case of errors when publishing */ + /* + * + * JANUS_VIDEOROOM_ERROR_NO_SUCH_FEED 428 + * JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT 429 + * JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT 430 + * JANUS_VIDEOROOM_ERROR_INVALID_SDP_TYPE 431 + * JANUS_VIDEOROOM_ERROR_PUBLISHERS_FULL 432 + * JANUS_VIDEOROOM_ERROR_UNAUTHORIZED 433 + * JANUS_VIDEOROOM_ERROR_ALREADY_PUBLISHED 434 + * JANUS_VIDEOROOM_ERROR_NOT_PUBLISHED 435 + * JANUS_VIDEOROOM_ERROR_ID_EXISTS 436 + * JANUS_VIDEOROOM_ERROR_INVALID_SDP 437 + * + */ + if (jsep && e._code && e._code >= 429 && e._code <= 437 && e._code != 434) + this.hangup().catch(() => { }); + throw e; + }); + + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.CONFIGURED && evtdata.configured === 'ok') { + if (body.display) evtdata.display = body.display; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Unpublish a feed in the room. + * + * @returns {Promise} + */ + async unpublish() { + const body = { + request: REQUEST_UNPUBLISH, + }; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.UNPUBLISHED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Join a room as subscriber. + * + * @param {object} params + * @param {number|string} params.room - The room to join + * @param {number|string} [params.feed=0] - The feed the user wants to subscribe to + * @param {boolean} [params.audio] - True to subscribe to the audio feed + * @param {boolean} [params.video] - True to subscribe to the video feed + * @param {boolean} [params.data] - True to subscribe to the datachannels of the feed + * @param {number} [params.private_id] - The private id to correlate with publisher + * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled + * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below + * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled + * @param {boolean} [params.autoupdate] - [multistream] Whether a new SDP offer is sent automatically when a subscribed publisher leaves + * @param {string} [params.token] - The optional token needed + * @returns {Promise} + */ + async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, autoupdate, token }) { + const body = { + request: REQUEST_JOIN, + ptype: PTYPE_LISTENER, + room, + feed, + }; + if (typeof audio === 'boolean') body.audio = audio; + if (typeof video === 'boolean') body.video = video; + if (typeof data === 'boolean') body.data = data; + if (typeof private_id === 'number') body.private_id = private_id; + if (typeof token === 'string') body.token = token; + if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; + if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; + if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; + // Multistream + if (typeof autoupdate === 'boolean') body.autoupdate = autoupdate; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.SUB_JOINED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Alias for "joinSubscriber". + * + * @see module:videoroom-plugin~VideoRoomHandle#joinSubscriber + */ + async joinListener(params) { + return this.joinSubscriber(params); + } + + /** + * Start a subscriber stream. + * + * @param {object} params + * @param {RTCSessionDescription} params.jsep - The JSEP answer + * @returns {Promise} + */ + async start({ jsep }) { + const body = { + request: REQUEST_START, + }; + + const response = await this.message(body, jsep); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.STARTED && evtdata.started === 'ok') + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Pause a subscriber feed. + * + * @returns {Promise} + */ + async pause() { + const body = { + request: REQUEST_PAUSE, + }; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.PAUSED && evtdata.paused === 'ok') + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Switch to another feed. + * + * @param {object} params + * @param {number|string} params.to_feed - The feed id of the new publisher to switch to + * @param {boolean} [params.audio] - True to subscribe to the audio feed + * @param {boolean} [params.video] - True to subscribe to the video feed + * @param {boolean} [params.data] - True to subscribe to the datachannels of the feed + * @returns {Promise} + */ + async switch({ to_feed, audio, video, data }) { + const body = { + request: REQUEST_SWITCH, + feed: to_feed, + }; + if (typeof audio === 'boolean') body.audio = audio; + if (typeof video === 'boolean') body.video = video; + if (typeof data === 'boolean') body.data = data; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.SWITCHED && evtdata.switched === 'ok') { + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Leave a room. + * Can be used by both publishers and subscribers. + * + * @returns {Promise} + */ + async leave() { + const body = { + request: REQUEST_LEAVE, + }; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.LEAVING) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * [multistream] Update a subscription. + * + * @returns {Promise} + */ + async update({ subscribe, unsubscribe }) { + const body = { + request: REQUEST_UPDATE, + }; + if (Array.isArray(subscribe)) body.subscribe = subscribe; + if (Array.isArray(unsubscribe)) body.unsubscribe = unsubscribe; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.UPDATED) { + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /*----------------*/ + /* Management API */ + /*----------------*/ + + /* These are the APIs needed to manage videoroom resources (rooms, forwarders ...) */ + + /** + * List the participants inside a room. + * + * @param {object} params + * @param {number|string} params.room - The room where the list is being requested + * @param {string} params.secret - The optional secret for the operation + * @returns {Promise} + */ + async listParticipants({ room, secret }) { + const body = { + request: REQUEST_LIST_PARTICIPANTS, + room, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.PARTICIPANTS_LIST) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Enable or disable recording for all participants in a room while the conference is in progress. + * + * @param {object} params + * @param {number|string} params.room - The room where the change of recording state is being requested + * @param {string} params.secret - The optional secret for the operation + * @param {boolean} params.record - True starts recording for all participants in an already running conference, false stops the recording + * @returns {Promise} + */ + async enable_recording({ room, secret, record }) { + const body = { + request: REQUEST_ENABLE_RECORDING, + room, + record + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.RECORDING_ENABLED_STATE) { + evtdata.room = body.room; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Kick a publisher out from a room. + * + * @param {object} params + * @param {number|string} params.room - The room where the kick is being requested + * @param {number|string} params.feed - The identifier of the feed to kick out + * @param {string} params.secret - The optional secret for the operation + * @returns {Promise} + */ + async kick({ room, feed, secret }) { + const body = { + request: REQUEST_KICK, + room, + id: feed, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.SUCCESS) { + evtdata.room = body.room; + evtdata.feed = body.id; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Check if a room exists. + * + * @param {object} params + * @param {number|string} params.room - The room to check + * @returns {Promise} + */ + async exists({ room }) { + const body = { + request: REQUEST_EXISTS, + room, + }; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.EXISTS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * List all the available rooms. + * + * @returns {Promise} + */ + async list() { + const body = { + request: REQUEST_LIST_ROOMS, + }; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.ROOMS_LIST) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Create a new room. + * + * @param {object} params + * @param {number|string} [params.room] - The room identifier, if missing picked by janus + * @param {string} [params.description] - A textual description of the room + * @param {number} [params.max_publishers] - The max number of publishers allowed + * @param {boolean} [params.permanent] - True to make Janus persist the room on th config file + * @param {boolean} [params.is_private] - Make the room private (hidden from listing) + * @param {string} [params.secret] - The secret that will be used to modify the room + * @param {string} [params.pin] - The pin needed to access the room + * @param {number} [params.bitrate] - The bitrate cap that will be used for publishers + * @param {boolean} [params.bitrate_cap] - Make the bitrate cap an insormountable limit + * @param {number} [params.fir_freq] - The PLI interval in seconds + * @param {string} [params.audiocodec] - Comma separated list of allowed audio codecs + * @param {string} [params.videocodec] - Comma separated list of allowed video codecs + * @param {boolean} [params.talking_events] - True to enable talking events + * @param {number} [params.talking_level_threshold] - Audio level threshold for talking events in the range [0, 127] + * @param {number} [params.talking_packets_threshold] - Audio packets threshold for talking events + * @param {boolean} [params.require_pvtid] - Whether subscriptions are required to provide a valid private_id + * @param {boolean} [params.require_e2ee] - Whether all participants are required to publish and subscribe using e2e encryption + * @param {boolean} [params.record] - Wheter to enable recording of any publisher + * @param {string} [params.rec_dir] - Folder where recordings should be stored + * @param {boolean} [params.videoorient] - Whether the video-orientation RTP extension must be negotiated + * @param {string} [params.h264_profile] - H264 specific profile to prefer + * @returns {Promise} + */ + async create({ room, description, max_publishers, permanent, is_private, secret, pin, bitrate, + bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, + require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile }) { + const body = { + request: REQUEST_CREATE, + }; + if (typeof room === 'string' || typeof room === 'number') body.room = room; + if (typeof description === 'string') body.description = description; + if (typeof max_publishers === 'number') body.publishers = max_publishers; + if (typeof permanent === 'boolean') body.permanent = permanent; + if (typeof is_private === 'boolean') body.is_private = is_private; + if (typeof secret === 'string') body.secret = secret; + if (typeof pin === 'string') body.pin = pin; + if (typeof bitrate === 'number') body.bitrate = bitrate; + if (typeof bitrate_cap === 'boolean') body.bitrate_cap = bitrate_cap; + if (typeof fir_freq === 'number') body.fir_freq = fir_freq; + if (typeof audiocodec === 'string') body.audiocodec = audiocodec; + if (typeof videocodec === 'string') body.videocodec = videocodec; + if (typeof talking_events === 'boolean') body.audiolevel_event = talking_events; + if (typeof talking_level_threshold === 'number' && talking_level_threshold >= 0 && talking_level_threshold <= 127) body.audio_level_average = talking_level_threshold; + if (typeof talking_packets_threshold === 'number' && talking_packets_threshold > 0) body.audio_active_packets = talking_packets_threshold; + if (typeof require_pvtid === 'boolean') body.require_pvtid = require_pvtid; + if (typeof require_e2ee === 'boolean') body.require_e2ee = require_e2ee; + if (typeof record === 'boolean') body.record = record; + if (typeof rec_dir === 'string') body.rec_dir = rec_dir; + if (typeof videoorient === 'boolean') body.videoorient_ext = videoorient; + if (typeof h264_profile === 'string') body.h264_profile = h264_profile; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.CREATED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Destroy a room. + * + * @param {object} params + * @param {number|string} params.room - The room to destroy + * @param {boolean} [params.permanent] - True to remove the room from the Janus config file + * @param {string} [params.secret] - The secret needed to manage the room + * @returns {Promise} + */ + async destroy({ room, permanent, secret }) { + const body = { + request: REQUEST_DESTROY, + room, + }; + if (typeof permanent === 'boolean') body.permanent = permanent; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.DESTROYED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Edit the ACL tokens for a room. + * + * @param {object} params + * @param {number|string} params.room - The room where to change the acl + * @param {"enable"|"disable"|"add"|"remove"} params.action - The action to execute on the acl + * @param {string[]} params.list - The list of tokens to execute the action onto + * @param {string} [params.secret] - The secret needed to manage the room + * @returns {Promise} + */ + async allow({ room, action, list, secret }) { + const body = { + request: REQUEST_ALLOW, + room, + action, + }; + if (list && list.length > 0) body.allowed = list; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.ALLOWED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Start a RTP forwarding in a room. + * + * @param {object} params + * @param {number|string} params.room - The room where to start a forwarder + * @param {number|string} params.feed - The feed identifier to forward (must be published) + * @param {string} params.host - The target host for the forwarder + * @param {number} [params.audio_port] - The target audio RTP port, if audio is to be forwarded + * @param {number} [params.audio_rtcp_port] - The target audio RTCP port, if audio is to be forwarded + * @param {number} [params.audio_ssrc] - The SSRC that will be used for audio RTP + * @param {number} [params.video_port] - The target video RTP port, if video is to be forwarded + * @param {number} [params.video_rtcp_port] - The target video RTCP port, if video is to be forwarded + * @param {number} [params.video_ssrc] - The SSRC that will be used for video RTP + * @param {number} [params.data_port] - The target datachannels port, if datachannels are to be forwarded + * @param {string} [params.secret] - The secret needed for managing the room + * @param {string} [params.admin_key] - The admin key needed for invoking the API + * @returns {Promise} + */ + async startForward({ room, feed, host, audio_port, audio_rtcp_port, audio_ssrc, video_port, video_rtcp_port, video_ssrc, data_port, secret, admin_key }) { + const body = { + request: REQUEST_RTP_FWD_START, + room, + publisher_id: feed, + }; + if (typeof host === 'string') body.host = host; + if (typeof audio_port === 'number') body.audio_port = audio_port; + if (typeof audio_rtcp_port === 'number') body.audio_rtcp_port = audio_rtcp_port; + if (typeof audio_ssrc === 'number') body.audio_ssrc = audio_ssrc; + if (typeof video_port === 'number') body.video_port = video_port; + if (typeof video_rtcp_port === 'number') body.video_rtcp_port = video_rtcp_port; + if (typeof video_ssrc === 'number') body.video_ssrc = video_ssrc; + if (typeof data_port === 'number') body.data_port = data_port; + if (typeof secret === 'string') body.secret = secret; + if (typeof admin_key === 'string') body.admin_key = admin_key; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.RTP_FWD_STARTED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Stop a RTP forwarder in a room. + * + * @param {object} params + * @param {number|string} params.room - The room where to stop a forwarder + * @param {number|string} params.feed - The feed identifier for the forwarder to stop (must be published) + * @param {number|string} params.stream - The forwarder identifier as returned by the start forward API + * @param {string} [params.secret] - The secret needed for managing the room + * @returns {Promise} + */ + async stopForward({ room, feed, stream, secret }) { + const body = { + request: REQUEST_RTP_FWD_STOP, + room, + publisher_id: feed, + stream_id: stream, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.RTP_FWD_STOPPED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * List the active forwarders in a room. + * + * @param {object} params + * @param {number|string} params.room - The room where to list the forwarders + * @param {string} [params.secret] - The secret needed for managing the room + * @returns {Promise} + */ + async listForward({ room, secret }) { + const body = { + request: REQUEST_RTP_FWD_LIST, + room, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.RTP_FWD_LIST) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + +} + +/** + * The payload of the plugin message (cfr. Janus docs). + * {@link https://janus.conf.meetecho.com/docs/videoroom.html} + * + * @private + * @typedef {object} VideoRoomData + */ + +/** + * The response event when a publisher has joined. + * + * @typedef {object} VIDEOROOM_EVENT_PUB_JOINED + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed identifier + * @property {string} [display] - The dsplay name, if available + * @property {string} description - A description of the room, if available + * @property {number} private_id - The private id that can be used when subscribing + * @property {object[]} publishers - The list of active publishers + * @property {number|string} publishers[].feed - The feed of an active publisher + * @property {string} [publishers[].display] - The display name of an active publisher + * @property {boolean} [publishers[].talking] - Whether the publisher is talking or not + * @property {string} [publishers[].audiocodec] - The audio codec used by active publisher + * @property {string} [publishers[].videocodec] - The video codec used by active publisher + * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) + * @property {object[]} [publishers[].streams] - [multistream] Streams description + * @property {RTCSessionDescription} [jsep] - The JSEP answer + */ + +/** + * The response event when a subscriber has joined. + * + * @typedef {object} VIDEOROOM_EVENT_SUB_JOINED + * @property {number|string} room - The involved room + * @property {number|string} feed - The published feed identifier + * @property {string} display - The published feed display name + */ + +/** + * The response event to a participant list request. + * + * @typedef {object} VIDEOROOM_EVENT_PARTICIPANTS_LIST + * @property {number|string} room - The involved room + * @property {number|string} feed - The current published feed + * @property {object[]} participants - The list of current participants + * @property {number|string} participants[].feed - Feed identifier of the participant + * @property {string} [participants[].display] - The participant's display name, if available + * @property {boolean} participants[].publisher - Whether the user is an active publisher in the room + * @property {boolean} [participants[].talking] - True if participant is talking + */ + +/** + * The response event for room create request. + * + * @typedef {object} VIDEOROOM_EVENT_CREATED + * @property {number|string} room - The created room + * @property {boolean} permanent - True if the room has been persisted on the Janus configuratin file + */ + +/** + * The response event for room destroy request. + * + * @typedef {object} VIDEOROOM_EVENT_DESTROYED + * @property {number|string} room - The destroyed room + * @property {boolean} permanent - True if the room has been removed from the Janus configuratin file + */ + +/** + * The response event for room exists request. + * + * @typedef {object} VIDEOROOM_EVENT_EXISTS + * @property {number|string} room - The queried room + */ + +/** + * Descriptrion of an active RTP forwarder. + * + * @typedef {object} RtpForwarder + * @property {string} host - The target host + * @property {number} [audio_port] - The RTP audio target port + * @property {number} [audio_rtcp_port] - The RTCP audio target port + * @property {number} [audio_stream] - The audio forwarder identifier + * @property {number} [video_port] - The RTP video target port + * @property {number} [video_rtcp_port] - The RTCP video target port + * @property {number} [video_stream] - The video forwarder identifier + * @property {number} [data_port] - The datachannels target port + * @property {number} [data_stream] - The datachannels forwarder identifier + * @property {number} [ssrc] - SSRC this forwarder is using + * @property {number} [pt] - payload type this forwarder is using + * @property {number} [sc_substream_layer] - video simulcast substream this video forwarder is relaying + * @property {boolean} [srtp] - whether the RTP stream is encrypted + */ + +/** + * The response event for RTP forward start request. + * + * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_STARTED + * @property {number|string} room - The involved room + * @property {RtpForwarder} forwarder - The forwarder object + */ + +/** + * The response event for RTP forward stop request. + * + * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_STOPPED + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed identifier being forwarded + * @property {number} stream - The forwarder identifier + */ + +/** + * The response event for RTP forwarders list request. + * + * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_LIST + * @property {number|string} room - The involved room + * @property {object[]} forwarders - The list of forwarders + * @property {number|string} forwarders[].feed - The feed that is being forwarded + * @property {RtpForwarder[]} forwarders[].forwarders -The list of the forwarders for this feed + */ + +/** + * The response event for videoroom list request. + * + * @typedef {object} VIDEOROOM_EVENT_LIST + * @property {object[]} list - The list of the room as returned by Janus + */ + +/** + * The response event for ACL tokens edit (allowed) request. + * + * @typedef {object} VIDEOROOM_EVENT_ALLOWED + * @property {string[]} list - The updated, complete, list of allowed tokens + */ + +/** + * The response event for publisher/subscriber configure request. + * + * @typedef {object} VIDEOROOM_EVENT_CONFIGURED + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed identifier + * @property {string} [display] - The display name, if available + * @property {boolean} [restart] - True if the request had it true + * @property {boolean} [update] - True if the request had it true + * @property {string} configured - A string with the value returned by Janus + * @property {RTCSessionDescription} [jsep] - The JSEP answer + */ + +/** + * The response event for subscriber start request. + * + * @typedef {object} VIDEOROOM_EVENT_STARTED + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that started + * @property {string} started - A string with the value returned by Janus + */ + +/** + * The response event for subscriber pause request. + * + * @typedef {object} VIDEOROOM_EVENT_PAUSED + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that has been paused + * @property {string} paused - A string with the value returned by Janus + */ + +/** + * The response event for subscriber switch request. + * + * @typedef {object} VIDEOROOM_EVENT_SWITCHED + * @property {number|string} room - The involved room + * @property {number|string} from_feed - The feed that has been switched from + * @property {number|string} to_feed - The feed that has been switched to + * @property {string} switched - A string with the value returned by Janus + * @property {string} display - The display name of the new feed + */ + +/** + * The response event for publisher unpublish request. + * + * @typedef {object} VIDEOROOM_EVENT_UNPUBLISHED + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that unpublished + */ + +/** + * The response event for publiher/subscriber leave request. + * + * @typedef {object} VIDEOROOM_EVENT_LEAVING + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that left + * @property {string} [reason] - An optional string with the reason of the leaving + */ + +/** + * The response event for the kick request. + * + * @typedef {object} VIDEOROOM_EVENT_KICKED + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that has been kicked + */ + +/** + * The response event for the recording enabled request. + * + * @typedef {object} VIDEOROOM_EVENT_RECORDING_ENABLED_STATE + * @property {number|string} room - The involved room + * @property {boolean} recording - Whether or not the room recording is now enabled + */ + +/** + * [multistream] The response event for update subscriber request. + * + * @typedef {object} VIDEOROOM_EVENT_UPDATED + * @property {number|string} room - The involved room + * @property {RTCSessionDescription} [jsep] - The updated JSEP offer + * @property {object[]} streams - List of the updated streams in this subscription + */ + +/** + * The exported plugin descriptor. + * + * @type {object} + * @property {string} id - The plugin identifier used when attaching to Janus + * @property {module:videoroom-plugin~VideoRoomHandle} Handle - The custom class implementing the plugin + * @property {object} EVENT - The events emitted by the plugin + * @property {string} EVENT.VIDEOROOM_PUB_PEER_JOINED {@link module:videoroom-plugin~VIDEOROOM_PUB_PEER_JOINED} + * @property {string} EVENT.VIDEOROOM_PUB_LIST {@link module:videoroom-plugin~VIDEOROOM_PUB_LIST} + * @property {string} EVENT.VIDEOROOM_DESTROYED {@link module:videoroom-plugin~VIDEOROOM_DESTROYED} + * @property {string} EVENT.VIDEOROOM_UNPUBLISHED {@link module:videoroom-plugin~VIDEOROOM_UNPUBLISHED} + * @property {string} EVENT.VIDEOROOM_LEAVING {@link module:videoroom-plugin~VIDEOROOM_LEAVING} + * @property {string} EVENT.VIDEOROOM_DISPLAY {@link module:videoroom-plugin~VIDEOROOM_DISPLAY} + * @property {string} EVENT.VIDEOROOM_KICKED {@link module:videoroom-plugin~VIDEOROOM_KICKED} + * @property {string} EVENT.VIDEOROOM_RECORDING_ENABLED_STATE {@link module:videoroom-plugin~VIDEOROOM_RECORDING_ENABLED_STATE} + * @property {string} EVENT.VIDEOROOM_TALKING {@link module:videoroom-plugin~VIDEOROOM_TALKING} + * @property {string} EVENT.VIDEOROOM_ERROR {@link module:videoroom-plugin~VIDEOROOM_ERROR} + */ +export default { + id: PLUGIN_ID, + Handle: VideoRoomHandle, + EVENT: { + /** + * A peer has joined theh room (notify-joining). + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_PUB_PEER_JOINED + * @type {object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed identifier that joined + * @property {string} display - The display name of the peer + */ + VIDEOROOM_PUB_PEER_JOINED: PLUGIN_EVENT.PUB_PEER_JOINED, + + /** + * Active publishers list updated. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_PUB_LIST + * @type {object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The current feed identifier + * @property {object[]} publishers - List of the new publishers + * @property {number|string} publishers[].feed - Feed identifier of the new publisher + * @property {string} publishers[].display - Display name of the new publisher + * @property {boolean} [publishers[].talking] - Whether the publisher is talking or not + * @property {string} [publishers[].audiocodec] - The audio codec used by active publisher + * @property {string} [publishers[].videocodec] - The video codec used by active publisher + * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) + * @property {object[]} [publishers[].streams] - [multistream] Streams description + */ + VIDEOROOM_PUB_LIST: PLUGIN_EVENT.PUB_LIST, + + /** + * The videoroom has been destroyed. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DESTROYED + * @type {module:videoroom-plugin~VIDEOROOM_EVENT_DESTROYED} + */ + VIDEOROOM_DESTROYED: PLUGIN_EVENT.DESTROYED, + + /** + * A feed has been unpublished. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UNPUBLISHED + * @type {module:videoroom-plugin~VIDEOROOM_EVENT_UNPUBLISHED} + */ + VIDEOROOM_UNPUBLISHED: PLUGIN_EVENT.UNPUBLISHED, + + /** + * A peer has left the room. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_LEAVING + * @type {module:videoroom-plugin~VIDEOROOM_EVENT_LEAVING} + */ + VIDEOROOM_LEAVING: PLUGIN_EVENT.LEAVING, + + /** + * A participant has changed the display name. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DISPLAY + * @type {object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed of the peer that change display name + * @property {string} display - The new display name of the peer + */ + VIDEOROOM_DISPLAY: PLUGIN_EVENT.DISPLAY, + + /** + * A handle received a configured event. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_CONFIGURED + * @type {module:videoroom-plugin~VIDEOROOM_EVENT_CONFIGURED} + */ + VIDEOROOM_CONFIGURED: PLUGIN_EVENT.CONFIGURED, + + /** + * A handle received a slow link notification. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DISPLAY + * @type {object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed of the peer that change display name + * @property {number} bitrate - The current bitrate cap for the participant + */ + VIDEOROOM_SLOWLINK: PLUGIN_EVENT.SLOW_LINK, + + /** + * Notify if the current user is talking. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_TALKING + * @type {object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed of the peer this talking notification refers to + * @property {boolean} talking - True if the participant is talking + * @property {number} audio_level - The audio level of the participant in the range [0,127] + */ + VIDEOROOM_TALKING: PLUGIN_EVENT.TALKING, + + /** + * A feed has been kicked out. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_KICKED + * @type {module:videoroom-plugin~VIDEOROOM_EVENT_KICKED} + */ + VIDEOROOM_KICKED: PLUGIN_EVENT.KICKED, + + /** + * Conference recording has been enabled or disabled. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_RECORDING_ENABLED_STATE + * @type {module:videoroom-plugin~VIDEOROOM_EVENT_RECORDING_ENABLED_STATE} + */ + VIDEOROOM_RECORDING_ENABLED_STATE: PLUGIN_EVENT.RECORDING_ENABLED_STATE, + + /** + * A switch to a different simulcast substream has been completed. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_SUBSTREAM_LAYER + * @type {object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed of the peer this notification refers to + * @property {number} sc_substream_layer - The new simuclast substream layer relayed + */ + VIDEOROOM_SC_SUBSTREAM_LAYER: PLUGIN_EVENT.SC_SUBSTREAM_LAYER, + + /** + * A switch to a different number of simulcast temporal layers has been completed. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_TEMPORAL_LAYERS + * @type {object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed of the peer this switch notification refers to + * @property {number} sc_temporal_layers - The new number of simuclast teporal layers relayed + */ + VIDEOROOM_SC_TEMPORAL_LAYERS: PLUGIN_EVENT.SC_TEMPORAL_LAYERS, + + /** + * A multistream subscription has been updated. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UPDATED + * @type {module:videoroom-plugin~VIDEOROOM_EVENT_UPDATED} + */ + VIDEOROOM_UPDATED: PLUGIN_EVENT.UPDATED, + + /** + * A generic videoroom error. + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_ERROR + * @type {Error} + */ + VIDEOROOM_ERROR: PLUGIN_EVENT.ERROR, + }, +}; From 4f9f5582b04a5a3d40b361f65a442fbbea9137e4 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 4 Sep 2023 11:38:54 +0200 Subject: [PATCH 010/114] WIP --- src/plugins/videoroom-ms-plugin.js | 1638 ---------------------------- 1 file changed, 1638 deletions(-) delete mode 100644 src/plugins/videoroom-ms-plugin.js diff --git a/src/plugins/videoroom-ms-plugin.js b/src/plugins/videoroom-ms-plugin.js deleted file mode 100644 index eebbc61..0000000 --- a/src/plugins/videoroom-ms-plugin.js +++ /dev/null @@ -1,1638 +0,0 @@ -'use strict'; - -/** - * This module contains the implementation of the VideoRoom multistream plugin (ref. {@link https://janus.conf.meetecho.com/docs/videoroom.html}). - * @module videoroom-ms-plugin - */ - -import Handle from '../handle.js'; - -/* The plugin ID exported in the plugin descriptor */ -const PLUGIN_ID = 'janus.plugin.videoroom-ms'; - -/* These are the requests defined for the Janus VideoRoom API */ -const REQUEST_JOIN = 'join'; -const REQUEST_CONFIGURE = 'configure'; -const REQUEST_JOIN_CONFIGURE = 'joinandconfigure'; -const REQUEST_LIST_PARTICIPANTS = 'listparticipants'; -const REQUEST_ENABLE_RECORDING = 'enable_recording'; -const REQUEST_KICK = 'kick'; -const REQUEST_START = 'start'; -const REQUEST_PAUSE = 'pause'; -const REQUEST_SWITCH = 'switch'; -const REQUEST_PUBLISH = 'publish'; -const REQUEST_UNPUBLISH = 'unpublish'; -const REQUEST_LEAVE = 'leave'; -const REQUEST_UPDATE = 'update'; - -const REQUEST_EXISTS = 'exists'; -const REQUEST_LIST_ROOMS = 'list'; -const REQUEST_CREATE = 'create'; -const REQUEST_DESTROY = 'destroy'; -const REQUEST_ALLOW = 'allowed'; - -const REQUEST_RTP_FWD_START = 'rtp_forward'; -const REQUEST_RTP_FWD_STOP = 'stop_rtp_forward'; -const REQUEST_RTP_FWD_LIST = 'listforwarders'; - -const PTYPE_PUBLISHER = 'publisher'; -const PTYPE_LISTENER = 'subscriber'; - -/* These are the events/responses that the Janode plugin will manage */ -/* Some of them will be exported in the plugin descriptor */ -const PLUGIN_EVENT = { - PUB_JOINED: 'videoroom_joined', - SUB_JOINED: 'videoroom_subscribed', - PUB_LIST: 'videoroom_publisher_list', - PARTICIPANTS_LIST: 'videoroom_participants_list', - PUB_PEER_JOINED: 'videoroom_publisher_joined', - STARTED: 'videoroom_started', - PAUSED: 'videoroom_paused', - SWITCHED: 'videoroom_switched', - CONFIGURED: 'videoroom_configured', - SLOW_LINK: 'videoroom_slowlink', - DISPLAY: 'videoroom_display', - UNPUBLISHED: 'videoroom_unpublished', - LEAVING: 'videoroom_leaving', - UPDATED: 'videoroom_updated', - KICKED: 'videoroom_kicked', - RECORDING_ENABLED_STATE: 'videoroom_recording_enabled_state', - TALKING: 'videoroom_talking', - SC_SUBSTREAM_LAYER: 'videoroom_sc_substream_layer', - SC_TEMPORAL_LAYERS: 'videoroom_sc_temporal_layers', - ALLOWED: 'videoroom_allowed', - EXISTS: 'videoroom_exists', - ROOMS_LIST: 'videoroom_list', - CREATED: 'videoroom_created', - DESTROYED: 'videoroom_destroyed', - RTP_FWD_STARTED: 'videoroom_rtp_fwd_started', - RTP_FWD_STOPPED: 'videoroom_rtp_fwd_stopped', - RTP_FWD_LIST: 'videoroom_rtp_fwd_list', - SUCCESS: 'videoroom_success', - ERROR: 'videoroom_error', -}; - -/** - * The class implementing the VideoRoom plugin (ref. {@link https://janus.conf.meetecho.com/docs/videoroom.html}).
- * - * It extends the base Janode Handle class and overrides the "handleMessage" method.
- * - * Moreover it defines many methods to support VideoRoom operations.
- * - * @hideconstructor - */ -class VideoRoomHandle extends Handle { - /** - * Create a Janode VideoRoom handle. - * - * @param {module:session~Session} session - A reference to the parent session - * @param {number} id - The handle identifier - */ - constructor(session, id) { - super(session, id); - - /** - * Either the feed identifier assigned to this publisher handle or the publisher's feed in case this handle is a subscriber. - * - * @type {number|string} - */ - this.feed = null; - - /** - * The identifier of the videoroom the handle has joined. - * - * @type {number|string} - */ - this.room = null; - } - - /** - * The custom "handleMessage" needed for handling VideoRoom messages. - * - * @private - * @param {object} janus_message - * @returns {object} A falsy value for unhandled events, a truthy value for handled events - */ - handleMessage(janus_message) { - const { plugindata, jsep, transaction } = janus_message; - if (plugindata && plugindata.data && plugindata.data.videoroom) { - /** - * @type {VideoRoomData} - */ - const message_data = plugindata.data; - const { videoroom, error, error_code, room } = message_data; - - /* Prepare an object for the output Janode event */ - const janode_event = { - /* The name of the resolved event */ - event: null, - /* The event payload */ - data: {}, - }; - - /* Add JSEP data if available */ - if (jsep) janode_event.data.jsep = jsep; - if (jsep && typeof jsep.e2ee === 'boolean') janode_event.data.e2ee = jsep.e2ee; - /* Add room information if available */ - if (room) janode_event.data.room = room; - - /* The plugin will emit an event only if the handle does not own the transaction */ - /* That means that a transaction has already been closed or this is an async event */ - const emit = (this.ownsTransaction(transaction) === false); - - /* Use the "janode" property to store the output event */ - janus_message._janode = janode_event; - - switch (videoroom) { - - /* Success response */ - case 'success': - /* Room exists API */ - if (typeof message_data.exists !== 'undefined') { - janode_event.data.exists = message_data.exists; - janode_event.event = PLUGIN_EVENT.EXISTS; - break; - } - /* Room list API */ - if (typeof message_data.list !== 'undefined') { - janode_event.data.list = message_data.list; - janode_event.event = PLUGIN_EVENT.ROOMS_LIST; - break; - } - /* Tokens management (add/remove/enable) */ - if (typeof message_data.allowed !== 'undefined') { - janode_event.data.list = message_data.allowed; - janode_event.event = PLUGIN_EVENT.ALLOWED; - break; - } - /* Global recording enabled or disabled */ - if (typeof message_data.record !== 'undefined') { - janode_event.data.record = message_data.record; - janode_event.event = PLUGIN_EVENT.RECORDING_ENABLED_STATE; - break; - } - - /* Generic success event */ - janode_event.event = PLUGIN_EVENT.SUCCESS; - break; - - /* Publisher joined */ - case 'joined': - /* Store room and feed id */ - this.room = room; - this.feed = message_data.id; - - janode_event.data.feed = message_data.id; - janode_event.data.description = message_data.description; - janode_event.data.private_id = message_data.private_id; - janode_event.data.publishers = message_data.publishers.map(({ id, display, streams }) => { - const pub = { - feed: id, - display, - }; - pub.streams = streams; - return pub; - }); - janode_event.event = PLUGIN_EVENT.PUB_JOINED; - break; - - /* Subscriber joined */ - case 'attached': - /* Store room and feed id */ - this.room = room; - this.feed = message_data.id; - - janode_event.data.feed = message_data.id; - janode_event.data.display = message_data.display; - janode_event.event = PLUGIN_EVENT.SUB_JOINED; - break; - - /* Slow-link event */ - case 'slow_link': - janode_event.data.feed = this.feed; - janode_event.data.bitrate = message_data['current-bitrate']; - janode_event.event = PLUGIN_EVENT.SLOW_LINK; - break; - - /* Participants list */ - case 'participants': - janode_event.data.participants = message_data.participants.map(({ id, display, publisher, talking }) => { - const peer = { - feed: id, - display, - publisher, - }; - if (typeof talking !== 'undefined') peer.talking = talking; - return peer; - }); - janode_event.event = PLUGIN_EVENT.PARTICIPANTS_LIST; - break; - - /* Room created */ - case 'created': - janode_event.event = PLUGIN_EVENT.CREATED; - janode_event.data.permanent = message_data.permanent; - break; - - /* Room destroyed */ - case 'destroyed': - janode_event.event = PLUGIN_EVENT.DESTROYED; - break; - - /* RTP forwarding started */ - case 'rtp_forward': - janode_event.data.feed = message_data.publisher_id; - janode_event.data.forwarder = { - host: message_data.rtp_stream.host, - }; - if (message_data.rtp_stream.audio) { - janode_event.data.forwarder.audio_port = message_data.rtp_stream.audio; - janode_event.data.forwarder.audio_rtcp_port = message_data.rtp_stream.audio_rtcp; - janode_event.data.forwarder.audio_stream = message_data.rtp_stream.audio_stream_id; - } - if (message_data.rtp_stream.video) { - janode_event.data.forwarder.video_port = message_data.rtp_stream.video; - janode_event.data.forwarder.video_rtcp_port = message_data.rtp_stream.video_rtcp; - janode_event.data.forwarder.video_stream = message_data.rtp_stream.video_stream_id; - } - if (message_data.rtp_stream.data) { - janode_event.data.forwarder.data_port = message_data.rtp_stream.data; - janode_event.data.forwarder.data_stream = message_data.rtp_stream.data_stream_id; - } - janode_event.event = PLUGIN_EVENT.RTP_FWD_STARTED; - break; - - /* RTP forwarding stopped */ - case 'stop_rtp_forward': - janode_event.data.feed = message_data.publisher_id; - janode_event.data.stream = message_data.stream_id; - janode_event.event = PLUGIN_EVENT.RTP_FWD_STOPPED; - break; - - /* RTP forwarders list */ - case 'forwarders': - if (janode_event.data.forwarders) { - janode_event.data.forwarders = message_data.rtp_forwarders.map(({ publisher_id, rtp_forwarder }) => { - const pub = { - feed: publisher_id, - }; - - pub.forwarders = rtp_forwarder.map(forw => { - const forwarder = { - host: forw.ip, - }; - - if (forw.audio_stream_id) { - forwarder.audio_port = forw.port; - forwarder.audio_rtcp_port = forw.remote_rtcp_port; - forwarder.audio_stream = forw.audio_stream_id; - } - if (forw.video_stream_id) { - forwarder.video_port = forw.port; - forwarder.video_rtcp_port = forw.remote_rtcp_port; - forwarder.video_stream = forw.video_stream_id; - } - if (forw.data_stream_id) { - forwarder.data_port = forw.port; - forwarder.data_stream = forw.data_stream_id; - } - - return forwarder; - }); - - return pub; - }); - } - else if (janode_event.data.publishers) { - janode_event.data.forwarders = message_data.publishers.map(({ publisher_id, forwarders }) => { - const pub = { - feed: publisher_id, - }; - - pub.forwarders = forwarders.map(forw => { - const forwarder = { - host: forw.host, - }; - - if (forw.type === 'audio') { - forwarder.audio_port = forw.port; - forwarder.audio_rtcp_port = forw.remote_rtcp_port; - forwarder.audio_stream = forw.stream_id; - } - if (forw.type === 'video') { - forwarder.video_port = forw.port; - forwarder.video_rtcp_port = forw.remote_rtcp_port; - forwarder.video_stream = forw.stream_id; - if (typeof forw.substream !== 'undefined') { - forwarder.sc_substream_layer = forw.substream; - } - } - if (forw.type === 'data') { - forwarder.data_port = forw.port; - forwarder.data_stream = forw.stream_id; - } - - if (typeof forw.ssrc !== 'undefined') - forwarder.ssrc = forw.ssrc; - if (typeof forw.pt !== 'undefined') - forwarder.pt = forw.pt; - if (typeof forw.srtp !== 'undefined') - forwarder.srtp = forw.srtp; - - return forwarder; - }); - - return pub; - }); - } - - janode_event.event = PLUGIN_EVENT.RTP_FWD_LIST; - break; - - /* Talking events */ - case 'talking': - case 'stopped-talking': - janode_event.data.feed = message_data.id; - janode_event.data.talking = (videoroom === 'talking'); - janode_event.data.audio_level = message_data['audio-level-dBov-avg']; - janode_event.event = PLUGIN_EVENT.TALKING; - break; - - /* [multistream] updated event */ - case 'updated': - janode_event.data.streams = message_data.streams; - janode_event.event = PLUGIN_EVENT.UPDATED; - break; - - /* [multistream] updating event, sent when janus receives another "update" before getting a JSEP answer for the previous one */ - case 'updating': - janode_event.data.streams = message_data.streams; - janode_event.event = PLUGIN_EVENT.UPDATED; - break; - - /* Generic events (error, notifications ...) */ - case 'event': - /* VideoRoom Error */ - if (error) { - janode_event.event = PLUGIN_EVENT.ERROR; - janode_event.data = new Error(`${error_code} ${error}`); - janode_event.data._code = error_code; - /* In case of error, close a transaction */ - this.closeTransactionWithError(transaction, janode_event.data); - break; - } - /* Participant joined notification (notify_joining) */ - if (message_data.joining) { - janode_event.event = PLUGIN_EVENT.PUB_PEER_JOINED; - janode_event.data.feed = message_data.joining.id; - if (message_data.joining.display) janode_event.data.display = message_data.joining.display; - break; - } - /* Publisher list notification */ - if (message_data.publishers) { - janode_event.event = PLUGIN_EVENT.PUB_LIST; - janode_event.data.publishers = message_data.publishers.map(({ id, display, talking, audio_codec, video_codec, simulcast, streams }) => { - const pub = { - feed: id, - display, - }; - if (typeof talking !== 'undefined') pub.talking = talking; - if (typeof audio_codec !== 'undefined') pub.audiocodec = audio_codec; - if (typeof video_codec !== 'undefined') pub.videocodec = video_codec; - if (typeof simulcast !== 'undefined') pub.simulcast = simulcast; - // Multistream - if (typeof streams !== 'undefined') pub.streams = streams; - return pub; - }); - break; - } - /* Configuration events (publishing, general configuration) */ - if (typeof message_data.configured !== 'undefined') { - janode_event.event = PLUGIN_EVENT.CONFIGURED; - janode_event.data.feed = this.feed; - janode_event.data.configured = message_data.configured; - break; - } - /* Display name changed event */ - if (typeof message_data.display !== 'undefined' && typeof message_data.switched === 'undefined') { - janode_event.event = PLUGIN_EVENT.DISPLAY; - janode_event.data.feed = message_data.id; - janode_event.data.display = message_data.display; - break; - } - /* Subscribed feed started */ - if (typeof message_data.started !== 'undefined') { - janode_event.event = PLUGIN_EVENT.STARTED; - janode_event.data.feed = this.feed; - janode_event.data.started = message_data.started; - break; - } - /* Subscribed feed paused */ - if (typeof message_data.paused !== 'undefined') { - janode_event.event = PLUGIN_EVENT.PAUSED; - janode_event.data.feed = this.feed; - janode_event.data.paused = message_data.paused; - break; - } - /* Subscribed feed switched */ - if (typeof message_data.switched !== 'undefined') { - janode_event.event = PLUGIN_EVENT.SWITCHED; - janode_event.data.switched = message_data.switched; - if (message_data.switched === 'ok' && typeof message_data.id !== 'undefined') { - janode_event.data.from_feed = this.feed; - this.feed = message_data.id; - janode_event.data.to_feed = this.feed; - janode_event.data.display = message_data.display; - } - break; - } - /* Unpublished own or other feed */ - if (typeof message_data.unpublished !== 'undefined') { - janode_event.event = PLUGIN_EVENT.UNPUBLISHED; - janode_event.data.feed = (message_data.unpublished === 'ok') ? this.feed : message_data.unpublished; - break; - } - /* Leaving confirmation */ - if (typeof message_data.leaving !== 'undefined') { - janode_event.event = PLUGIN_EVENT.LEAVING; - janode_event.data.feed = (message_data.leaving === 'ok') ? this.feed : message_data.leaving; - if (message_data.reason) janode_event.data.reason = message_data.reason; - break; - } - /* Participant kicked out */ - if (typeof message_data.kicked !== 'undefined') { - janode_event.event = PLUGIN_EVENT.KICKED; - janode_event.data.feed = message_data.kicked; - break; - } - /* Participant left (for subscribers "leave") */ - if (typeof message_data.left !== 'undefined') { - janode_event.event = PLUGIN_EVENT.LEAVING; - janode_event.data.feed = this.feed; - break; - } - /* Simulcast substream layer switch */ - if (typeof message_data.substream !== 'undefined') { - janode_event.event = PLUGIN_EVENT.SC_SUBSTREAM_LAYER; - janode_event.data.feed = this.feed; - janode_event.data.sc_substream_layer = message_data.substream; - break; - } - /* Simulcast temporal layers switch */ - if (typeof message_data.temporal !== 'undefined') { - janode_event.event = PLUGIN_EVENT.SC_TEMPORAL_LAYERS; - janode_event.data.feed = this.feed; - janode_event.data.sc_temporal_layers = message_data.temporal; - break; - } - } - - /* The event has been handled */ - if (janode_event.event) { - /* Try to close the transaction */ - this.closeTransactionWithSuccess(transaction, janus_message); - /* If the transaction was not owned, emit the event */ - if (emit) this.emit(janode_event.event, janode_event.data); - return janode_event; - } - } - - /* The event has not been handled, return a falsy value */ - return null; - } - - /*----------*/ - /* USER API */ - /*----------*/ - - /* These are the APIs that users need to work with the videoroom plugin */ - - /** - * Join a videoroom as publisher. - * - * @param {object} params - * @param {number|string} params.room - The room to join to - * @param {number|string} [params.feed] - The feed identifier to use, if missing it is picked by Janus - * @param {string} [params.display] - The display name to use - * @param {string} [params.token] - The optional token needed to join the room - * @param {string} [params.pin] - The optional pin needed to join the room - * @returns {Promise} - */ - async joinPublisher({ room, feed, display, token, pin }) { - const body = { - request: REQUEST_JOIN, - ptype: PTYPE_PUBLISHER, - room, - }; - if (typeof feed === 'string' || typeof feed === 'number') body.id = feed; - if (typeof display === 'string') body.display = display; - if (typeof token === 'string') body.token = token; - if (typeof pin === 'string') body.pin = pin; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.PUB_JOINED) { - if (body.display) evtdata.display = body.display; - return evtdata; - } - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Join and configure videoroom handle as publisher. - * - * @param {object} params - * @param {number|string} params.room - The room to join to - * @param {number|string} [params.feed] - The feed identifier to use, if missing it is picked by Janus - * @param {object[]} params.streams - * @param {string} [params.display] - The display name to use - * @param {string} [params.token] - The optional token needed to join the room - * @param {string} [params.pin] - The optional pin needed to join the room - * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection - * @param {RTCSessionDescription} [params.jsep] - The JSEP offer - * @returns {Promise} - */ - async joinConfigurePublisher({ room, feed, streams, bitrate, record, filename, display, token, pin, e2ee, jsep }) { - const body = { - request: REQUEST_JOIN_CONFIGURE, - ptype: PTYPE_PUBLISHER, - room, - }; - if (typeof feed === 'string' || typeof feed === 'number') body.id = feed; - if (typeof display === 'string') body.display = display; - if (Array.isArray(streams)) body.streams = streams; - if (typeof bitrate === 'number') body.bitrate = bitrate; - if (typeof record === 'boolean') body.record = record; - if (typeof filename === 'string') body.filename = filename; - if (typeof token === 'string') body.token = token; - if (typeof pin === 'string') body.pin = pin; - if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; - - const response = await this.message(body, jsep).catch(e => { - /* Cleanup the WebRTC status in Janus in case of errors when publishing */ - /* - * - * JANUS_VIDEOROOM_ERROR_NO_SUCH_FEED 428 - * JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT 429 - * JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT 430 - * JANUS_VIDEOROOM_ERROR_INVALID_SDP_TYPE 431 - * JANUS_VIDEOROOM_ERROR_PUBLISHERS_FULL 432 - * JANUS_VIDEOROOM_ERROR_UNAUTHORIZED 433 - * JANUS_VIDEOROOM_ERROR_ALREADY_PUBLISHED 434 - * JANUS_VIDEOROOM_ERROR_NOT_PUBLISHED 435 - * JANUS_VIDEOROOM_ERROR_ID_EXISTS 436 - * JANUS_VIDEOROOM_ERROR_INVALID_SDP 437 - * - */ - if (jsep && e._code && e._code >= 429 && e._code <= 437 && e._code != 434) - this.hangup().catch(() => { }); - throw e; - }); - - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.PUB_JOINED) { - if (body.display) evtdata.display = body.display; - return evtdata; - } - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Configure a publisher or subscriber handle.
- * Room is detected from the context since a handle must have joined before.
- * Can also be used by publishers to publish a feed.
- * - * Use this API also to trigger ICE restarts. Publishers can omit the - * restart/update flags, while subscribers need to use them to force - * the operation. - * - * @param {object} params - * @param {boolean} [params.audio] - True to request audio relaying - * @param {boolean} [params.video] - True to request video relaying - * @param {boolean} [params.data] - True to request datachannel relaying - * @param {string} [params.display] - The display name to use (publishers only) - * @param {number} [params.bitrate] - Bitrate cap (publishers only) - * @param {boolean} [params.record] - True to record the feed (publishers only) - * @param {string} [params.filename] - If recording, the base path/file to use for the recording (publishers only) - * @param {boolean} [params.restart] - Set to force a ICE restart - * @param {boolean} [params.update] - Set to force a renegotiation - * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled (subscribers only) - * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below (subscribers only) - * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled (subscribers only) - * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection - * @param {RTCSessionDescription} [params.jsep] - The JSEP offer (publishers only) - * @returns {Promise} - */ - async configure({ audio, video, data, bitrate, record, filename, display, restart, update, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, e2ee, jsep }) { - const body = { - request: REQUEST_CONFIGURE, - }; - if (typeof audio === 'boolean') body.audio = audio; - if (typeof video === 'boolean') body.video = video; - if (typeof data === 'boolean') body.data = data; - if (typeof bitrate === 'number') body.bitrate = bitrate; - if (typeof record === 'boolean') body.record = record; - if (typeof filename === 'string') body.filename = filename; - if (typeof display === 'string') body.display = display; - if (typeof restart === 'boolean') body.restart = restart; - if (typeof update === 'boolean') body.update = update; - if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; - if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; - if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; - if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; - - const response = await this.message(body, jsep).catch(e => { - /* Cleanup the WebRTC status in Janus in case of errors when publishing */ - /* - * - * JANUS_VIDEOROOM_ERROR_NO_SUCH_FEED 428 - * JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT 429 - * JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT 430 - * JANUS_VIDEOROOM_ERROR_INVALID_SDP_TYPE 431 - * JANUS_VIDEOROOM_ERROR_PUBLISHERS_FULL 432 - * JANUS_VIDEOROOM_ERROR_UNAUTHORIZED 433 - * JANUS_VIDEOROOM_ERROR_ALREADY_PUBLISHED 434 - * JANUS_VIDEOROOM_ERROR_NOT_PUBLISHED 435 - * JANUS_VIDEOROOM_ERROR_ID_EXISTS 436 - * JANUS_VIDEOROOM_ERROR_INVALID_SDP 437 - * - */ - if (jsep && e._code && e._code >= 429 && e._code <= 437 && e._code != 434) - this.hangup().catch(() => { }); - throw e; - }); - - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.CONFIGURED && evtdata.configured === 'ok') { - if (body.display) evtdata.display = body.display; - if (typeof body.request === 'boolean') evtdata.restart = body.restart; - if (typeof body.update === 'boolean') evtdata.update = body.update; - return evtdata; - } - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Publish a feed in the room. - * Room is detected from the context since a handle must have joined before. - * - * @param {object} params - * @param {boolean} [params.audio] - True to request audio relaying - * @param {boolean} [params.video] - True to request video relaying - * @param {boolean} [params.data] - True to request datachannel relaying - * @param {string} [params.display] - The display name to use - * @param {number} [params.bitrate] - Bitrate cap - * @param {boolean} [params.record] - True to record the feed - * @param {string} [params.filename] - If recording, the base path/file to use for the recording - * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection - * @param {RTCSessionDescription} params.jsep - The JSEP offer - * @returns {Promise} - */ - async publish({ audio, video, data, bitrate, record, filename, display, e2ee, jsep }) { - if (typeof jsep === 'object' && jsep && jsep.type !== 'offer') { - const error = new Error('jsep must be an offer'); - return Promise.reject(error); - } - const body = { - request: REQUEST_PUBLISH, - }; - if (typeof audio === 'boolean') body.audio = audio; - if (typeof video === 'boolean') body.video = video; - if (typeof data === 'boolean') body.data = data; - if (typeof bitrate === 'number') body.bitrate = bitrate; - if (typeof record === 'boolean') body.record = record; - if (typeof filename === 'string') body.filename = filename; - if (typeof display === 'string') body.display = display; - if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; - - const response = await this.message(body, jsep).catch(e => { - /* Cleanup the WebRTC status in Janus in case of errors when publishing */ - /* - * - * JANUS_VIDEOROOM_ERROR_NO_SUCH_FEED 428 - * JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT 429 - * JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT 430 - * JANUS_VIDEOROOM_ERROR_INVALID_SDP_TYPE 431 - * JANUS_VIDEOROOM_ERROR_PUBLISHERS_FULL 432 - * JANUS_VIDEOROOM_ERROR_UNAUTHORIZED 433 - * JANUS_VIDEOROOM_ERROR_ALREADY_PUBLISHED 434 - * JANUS_VIDEOROOM_ERROR_NOT_PUBLISHED 435 - * JANUS_VIDEOROOM_ERROR_ID_EXISTS 436 - * JANUS_VIDEOROOM_ERROR_INVALID_SDP 437 - * - */ - if (jsep && e._code && e._code >= 429 && e._code <= 437 && e._code != 434) - this.hangup().catch(() => { }); - throw e; - }); - - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.CONFIGURED && evtdata.configured === 'ok') { - if (body.display) evtdata.display = body.display; - return evtdata; - } - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Unpublish a feed in the room. - * - * @returns {Promise} - */ - async unpublish() { - const body = { - request: REQUEST_UNPUBLISH, - }; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.UNPUBLISHED) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Join a room as subscriber. - * - * @param {object} params - * @param {number|string} params.room - The room to join - * @param {number|string} [params.feed=0] - The feed the user wants to subscribe to - * @param {boolean} [params.audio] - True to subscribe to the audio feed - * @param {boolean} [params.video] - True to subscribe to the video feed - * @param {boolean} [params.data] - True to subscribe to the datachannels of the feed - * @param {number} [params.private_id] - The private id to correlate with publisher - * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled - * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below - * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled - * @param {boolean} [params.autoupdate] - [multistream] Whether a new SDP offer is sent automatically when a subscribed publisher leaves - * @param {string} [params.token] - The optional token needed - * @returns {Promise} - */ - async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, autoupdate, token }) { - const body = { - request: REQUEST_JOIN, - ptype: PTYPE_LISTENER, - room, - feed, - }; - if (typeof audio === 'boolean') body.audio = audio; - if (typeof video === 'boolean') body.video = video; - if (typeof data === 'boolean') body.data = data; - if (typeof private_id === 'number') body.private_id = private_id; - if (typeof token === 'string') body.token = token; - if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; - if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; - if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; - // Multistream - if (typeof autoupdate === 'boolean') body.autoupdate = autoupdate; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.SUB_JOINED) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Alias for "joinSubscriber". - * - * @see module:videoroom-plugin~VideoRoomHandle#joinSubscriber - */ - async joinListener(params) { - return this.joinSubscriber(params); - } - - /** - * Start a subscriber stream. - * - * @param {object} params - * @param {RTCSessionDescription} params.jsep - The JSEP answer - * @returns {Promise} - */ - async start({ jsep }) { - const body = { - request: REQUEST_START, - }; - - const response = await this.message(body, jsep); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.STARTED && evtdata.started === 'ok') - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Pause a subscriber feed. - * - * @returns {Promise} - */ - async pause() { - const body = { - request: REQUEST_PAUSE, - }; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.PAUSED && evtdata.paused === 'ok') - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Switch to another feed. - * - * @param {object} params - * @param {number|string} params.to_feed - The feed id of the new publisher to switch to - * @param {boolean} [params.audio] - True to subscribe to the audio feed - * @param {boolean} [params.video] - True to subscribe to the video feed - * @param {boolean} [params.data] - True to subscribe to the datachannels of the feed - * @returns {Promise} - */ - async switch({ to_feed, audio, video, data }) { - const body = { - request: REQUEST_SWITCH, - feed: to_feed, - }; - if (typeof audio === 'boolean') body.audio = audio; - if (typeof video === 'boolean') body.video = video; - if (typeof data === 'boolean') body.data = data; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.SWITCHED && evtdata.switched === 'ok') { - return evtdata; - } - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Leave a room. - * Can be used by both publishers and subscribers. - * - * @returns {Promise} - */ - async leave() { - const body = { - request: REQUEST_LEAVE, - }; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.LEAVING) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * [multistream] Update a subscription. - * - * @returns {Promise} - */ - async update({ subscribe, unsubscribe }) { - const body = { - request: REQUEST_UPDATE, - }; - if (Array.isArray(subscribe)) body.subscribe = subscribe; - if (Array.isArray(unsubscribe)) body.unsubscribe = unsubscribe; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.UPDATED) { - return evtdata; - } - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /*----------------*/ - /* Management API */ - /*----------------*/ - - /* These are the APIs needed to manage videoroom resources (rooms, forwarders ...) */ - - /** - * List the participants inside a room. - * - * @param {object} params - * @param {number|string} params.room - The room where the list is being requested - * @param {string} params.secret - The optional secret for the operation - * @returns {Promise} - */ - async listParticipants({ room, secret }) { - const body = { - request: REQUEST_LIST_PARTICIPANTS, - room, - }; - if (typeof secret === 'string') body.secret = secret; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.PARTICIPANTS_LIST) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Enable or disable recording for all participants in a room while the conference is in progress. - * - * @param {object} params - * @param {number|string} params.room - The room where the change of recording state is being requested - * @param {string} params.secret - The optional secret for the operation - * @param {boolean} params.record - True starts recording for all participants in an already running conference, false stops the recording - * @returns {Promise} - */ - async enable_recording({ room, secret, record }) { - const body = { - request: REQUEST_ENABLE_RECORDING, - room, - record - }; - if (typeof secret === 'string') body.secret = secret; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.RECORDING_ENABLED_STATE) { - evtdata.room = body.room; - return evtdata; - } - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Kick a publisher out from a room. - * - * @param {object} params - * @param {number|string} params.room - The room where the kick is being requested - * @param {number|string} params.feed - The identifier of the feed to kick out - * @param {string} params.secret - The optional secret for the operation - * @returns {Promise} - */ - async kick({ room, feed, secret }) { - const body = { - request: REQUEST_KICK, - room, - id: feed, - }; - if (typeof secret === 'string') body.secret = secret; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.SUCCESS) { - evtdata.room = body.room; - evtdata.feed = body.id; - return evtdata; - } - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Check if a room exists. - * - * @param {object} params - * @param {number|string} params.room - The room to check - * @returns {Promise} - */ - async exists({ room }) { - const body = { - request: REQUEST_EXISTS, - room, - }; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.EXISTS) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * List all the available rooms. - * - * @returns {Promise} - */ - async list() { - const body = { - request: REQUEST_LIST_ROOMS, - }; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.ROOMS_LIST) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Create a new room. - * - * @param {object} params - * @param {number|string} [params.room] - The room identifier, if missing picked by janus - * @param {string} [params.description] - A textual description of the room - * @param {number} [params.max_publishers] - The max number of publishers allowed - * @param {boolean} [params.permanent] - True to make Janus persist the room on th config file - * @param {boolean} [params.is_private] - Make the room private (hidden from listing) - * @param {string} [params.secret] - The secret that will be used to modify the room - * @param {string} [params.pin] - The pin needed to access the room - * @param {number} [params.bitrate] - The bitrate cap that will be used for publishers - * @param {boolean} [params.bitrate_cap] - Make the bitrate cap an insormountable limit - * @param {number} [params.fir_freq] - The PLI interval in seconds - * @param {string} [params.audiocodec] - Comma separated list of allowed audio codecs - * @param {string} [params.videocodec] - Comma separated list of allowed video codecs - * @param {boolean} [params.talking_events] - True to enable talking events - * @param {number} [params.talking_level_threshold] - Audio level threshold for talking events in the range [0, 127] - * @param {number} [params.talking_packets_threshold] - Audio packets threshold for talking events - * @param {boolean} [params.require_pvtid] - Whether subscriptions are required to provide a valid private_id - * @param {boolean} [params.require_e2ee] - Whether all participants are required to publish and subscribe using e2e encryption - * @param {boolean} [params.record] - Wheter to enable recording of any publisher - * @param {string} [params.rec_dir] - Folder where recordings should be stored - * @param {boolean} [params.videoorient] - Whether the video-orientation RTP extension must be negotiated - * @param {string} [params.h264_profile] - H264 specific profile to prefer - * @returns {Promise} - */ - async create({ room, description, max_publishers, permanent, is_private, secret, pin, bitrate, - bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, - require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile }) { - const body = { - request: REQUEST_CREATE, - }; - if (typeof room === 'string' || typeof room === 'number') body.room = room; - if (typeof description === 'string') body.description = description; - if (typeof max_publishers === 'number') body.publishers = max_publishers; - if (typeof permanent === 'boolean') body.permanent = permanent; - if (typeof is_private === 'boolean') body.is_private = is_private; - if (typeof secret === 'string') body.secret = secret; - if (typeof pin === 'string') body.pin = pin; - if (typeof bitrate === 'number') body.bitrate = bitrate; - if (typeof bitrate_cap === 'boolean') body.bitrate_cap = bitrate_cap; - if (typeof fir_freq === 'number') body.fir_freq = fir_freq; - if (typeof audiocodec === 'string') body.audiocodec = audiocodec; - if (typeof videocodec === 'string') body.videocodec = videocodec; - if (typeof talking_events === 'boolean') body.audiolevel_event = talking_events; - if (typeof talking_level_threshold === 'number' && talking_level_threshold >= 0 && talking_level_threshold <= 127) body.audio_level_average = talking_level_threshold; - if (typeof talking_packets_threshold === 'number' && talking_packets_threshold > 0) body.audio_active_packets = talking_packets_threshold; - if (typeof require_pvtid === 'boolean') body.require_pvtid = require_pvtid; - if (typeof require_e2ee === 'boolean') body.require_e2ee = require_e2ee; - if (typeof record === 'boolean') body.record = record; - if (typeof rec_dir === 'string') body.rec_dir = rec_dir; - if (typeof videoorient === 'boolean') body.videoorient_ext = videoorient; - if (typeof h264_profile === 'string') body.h264_profile = h264_profile; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.CREATED) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Destroy a room. - * - * @param {object} params - * @param {number|string} params.room - The room to destroy - * @param {boolean} [params.permanent] - True to remove the room from the Janus config file - * @param {string} [params.secret] - The secret needed to manage the room - * @returns {Promise} - */ - async destroy({ room, permanent, secret }) { - const body = { - request: REQUEST_DESTROY, - room, - }; - if (typeof permanent === 'boolean') body.permanent = permanent; - if (typeof secret === 'string') body.secret = secret; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.DESTROYED) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Edit the ACL tokens for a room. - * - * @param {object} params - * @param {number|string} params.room - The room where to change the acl - * @param {"enable"|"disable"|"add"|"remove"} params.action - The action to execute on the acl - * @param {string[]} params.list - The list of tokens to execute the action onto - * @param {string} [params.secret] - The secret needed to manage the room - * @returns {Promise} - */ - async allow({ room, action, list, secret }) { - const body = { - request: REQUEST_ALLOW, - room, - action, - }; - if (list && list.length > 0) body.allowed = list; - if (typeof secret === 'string') body.secret = secret; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.ALLOWED) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Start a RTP forwarding in a room. - * - * @param {object} params - * @param {number|string} params.room - The room where to start a forwarder - * @param {number|string} params.feed - The feed identifier to forward (must be published) - * @param {string} params.host - The target host for the forwarder - * @param {number} [params.audio_port] - The target audio RTP port, if audio is to be forwarded - * @param {number} [params.audio_rtcp_port] - The target audio RTCP port, if audio is to be forwarded - * @param {number} [params.audio_ssrc] - The SSRC that will be used for audio RTP - * @param {number} [params.video_port] - The target video RTP port, if video is to be forwarded - * @param {number} [params.video_rtcp_port] - The target video RTCP port, if video is to be forwarded - * @param {number} [params.video_ssrc] - The SSRC that will be used for video RTP - * @param {number} [params.data_port] - The target datachannels port, if datachannels are to be forwarded - * @param {string} [params.secret] - The secret needed for managing the room - * @param {string} [params.admin_key] - The admin key needed for invoking the API - * @returns {Promise} - */ - async startForward({ room, feed, host, audio_port, audio_rtcp_port, audio_ssrc, video_port, video_rtcp_port, video_ssrc, data_port, secret, admin_key }) { - const body = { - request: REQUEST_RTP_FWD_START, - room, - publisher_id: feed, - }; - if (typeof host === 'string') body.host = host; - if (typeof audio_port === 'number') body.audio_port = audio_port; - if (typeof audio_rtcp_port === 'number') body.audio_rtcp_port = audio_rtcp_port; - if (typeof audio_ssrc === 'number') body.audio_ssrc = audio_ssrc; - if (typeof video_port === 'number') body.video_port = video_port; - if (typeof video_rtcp_port === 'number') body.video_rtcp_port = video_rtcp_port; - if (typeof video_ssrc === 'number') body.video_ssrc = video_ssrc; - if (typeof data_port === 'number') body.data_port = data_port; - if (typeof secret === 'string') body.secret = secret; - if (typeof admin_key === 'string') body.admin_key = admin_key; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.RTP_FWD_STARTED) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * Stop a RTP forwarder in a room. - * - * @param {object} params - * @param {number|string} params.room - The room where to stop a forwarder - * @param {number|string} params.feed - The feed identifier for the forwarder to stop (must be published) - * @param {number|string} params.stream - The forwarder identifier as returned by the start forward API - * @param {string} [params.secret] - The secret needed for managing the room - * @returns {Promise} - */ - async stopForward({ room, feed, stream, secret }) { - const body = { - request: REQUEST_RTP_FWD_STOP, - room, - publisher_id: feed, - stream_id: stream, - }; - if (typeof secret === 'string') body.secret = secret; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.RTP_FWD_STOPPED) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - - /** - * List the active forwarders in a room. - * - * @param {object} params - * @param {number|string} params.room - The room where to list the forwarders - * @param {string} [params.secret] - The secret needed for managing the room - * @returns {Promise} - */ - async listForward({ room, secret }) { - const body = { - request: REQUEST_RTP_FWD_LIST, - room, - }; - if (typeof secret === 'string') body.secret = secret; - - const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; - if (event === PLUGIN_EVENT.RTP_FWD_LIST) - return evtdata; - const error = new Error(`unexpected response to ${body.request} request`); - throw (error); - } - -} - -/** - * The payload of the plugin message (cfr. Janus docs). - * {@link https://janus.conf.meetecho.com/docs/videoroom.html} - * - * @private - * @typedef {object} VideoRoomData - */ - -/** - * The response event when a publisher has joined. - * - * @typedef {object} VIDEOROOM_EVENT_PUB_JOINED - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed identifier - * @property {string} [display] - The dsplay name, if available - * @property {string} description - A description of the room, if available - * @property {number} private_id - The private id that can be used when subscribing - * @property {object[]} publishers - The list of active publishers - * @property {number|string} publishers[].feed - The feed of an active publisher - * @property {string} [publishers[].display] - The display name of an active publisher - * @property {boolean} [publishers[].talking] - Whether the publisher is talking or not - * @property {string} [publishers[].audiocodec] - The audio codec used by active publisher - * @property {string} [publishers[].videocodec] - The video codec used by active publisher - * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) - * @property {object[]} [publishers[].streams] - [multistream] Streams description - * @property {RTCSessionDescription} [jsep] - The JSEP answer - */ - -/** - * The response event when a subscriber has joined. - * - * @typedef {object} VIDEOROOM_EVENT_SUB_JOINED - * @property {number|string} room - The involved room - * @property {number|string} feed - The published feed identifier - * @property {string} display - The published feed display name - */ - -/** - * The response event to a participant list request. - * - * @typedef {object} VIDEOROOM_EVENT_PARTICIPANTS_LIST - * @property {number|string} room - The involved room - * @property {number|string} feed - The current published feed - * @property {object[]} participants - The list of current participants - * @property {number|string} participants[].feed - Feed identifier of the participant - * @property {string} [participants[].display] - The participant's display name, if available - * @property {boolean} participants[].publisher - Whether the user is an active publisher in the room - * @property {boolean} [participants[].talking] - True if participant is talking - */ - -/** - * The response event for room create request. - * - * @typedef {object} VIDEOROOM_EVENT_CREATED - * @property {number|string} room - The created room - * @property {boolean} permanent - True if the room has been persisted on the Janus configuratin file - */ - -/** - * The response event for room destroy request. - * - * @typedef {object} VIDEOROOM_EVENT_DESTROYED - * @property {number|string} room - The destroyed room - * @property {boolean} permanent - True if the room has been removed from the Janus configuratin file - */ - -/** - * The response event for room exists request. - * - * @typedef {object} VIDEOROOM_EVENT_EXISTS - * @property {number|string} room - The queried room - */ - -/** - * Descriptrion of an active RTP forwarder. - * - * @typedef {object} RtpForwarder - * @property {string} host - The target host - * @property {number} [audio_port] - The RTP audio target port - * @property {number} [audio_rtcp_port] - The RTCP audio target port - * @property {number} [audio_stream] - The audio forwarder identifier - * @property {number} [video_port] - The RTP video target port - * @property {number} [video_rtcp_port] - The RTCP video target port - * @property {number} [video_stream] - The video forwarder identifier - * @property {number} [data_port] - The datachannels target port - * @property {number} [data_stream] - The datachannels forwarder identifier - * @property {number} [ssrc] - SSRC this forwarder is using - * @property {number} [pt] - payload type this forwarder is using - * @property {number} [sc_substream_layer] - video simulcast substream this video forwarder is relaying - * @property {boolean} [srtp] - whether the RTP stream is encrypted - */ - -/** - * The response event for RTP forward start request. - * - * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_STARTED - * @property {number|string} room - The involved room - * @property {RtpForwarder} forwarder - The forwarder object - */ - -/** - * The response event for RTP forward stop request. - * - * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_STOPPED - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed identifier being forwarded - * @property {number} stream - The forwarder identifier - */ - -/** - * The response event for RTP forwarders list request. - * - * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_LIST - * @property {number|string} room - The involved room - * @property {object[]} forwarders - The list of forwarders - * @property {number|string} forwarders[].feed - The feed that is being forwarded - * @property {RtpForwarder[]} forwarders[].forwarders -The list of the forwarders for this feed - */ - -/** - * The response event for videoroom list request. - * - * @typedef {object} VIDEOROOM_EVENT_LIST - * @property {object[]} list - The list of the room as returned by Janus - */ - -/** - * The response event for ACL tokens edit (allowed) request. - * - * @typedef {object} VIDEOROOM_EVENT_ALLOWED - * @property {string[]} list - The updated, complete, list of allowed tokens - */ - -/** - * The response event for publisher/subscriber configure request. - * - * @typedef {object} VIDEOROOM_EVENT_CONFIGURED - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed identifier - * @property {string} [display] - The display name, if available - * @property {boolean} [restart] - True if the request had it true - * @property {boolean} [update] - True if the request had it true - * @property {string} configured - A string with the value returned by Janus - * @property {RTCSessionDescription} [jsep] - The JSEP answer - */ - -/** - * The response event for subscriber start request. - * - * @typedef {object} VIDEOROOM_EVENT_STARTED - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed that started - * @property {string} started - A string with the value returned by Janus - */ - -/** - * The response event for subscriber pause request. - * - * @typedef {object} VIDEOROOM_EVENT_PAUSED - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed that has been paused - * @property {string} paused - A string with the value returned by Janus - */ - -/** - * The response event for subscriber switch request. - * - * @typedef {object} VIDEOROOM_EVENT_SWITCHED - * @property {number|string} room - The involved room - * @property {number|string} from_feed - The feed that has been switched from - * @property {number|string} to_feed - The feed that has been switched to - * @property {string} switched - A string with the value returned by Janus - * @property {string} display - The display name of the new feed - */ - -/** - * The response event for publisher unpublish request. - * - * @typedef {object} VIDEOROOM_EVENT_UNPUBLISHED - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed that unpublished - */ - -/** - * The response event for publiher/subscriber leave request. - * - * @typedef {object} VIDEOROOM_EVENT_LEAVING - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed that left - * @property {string} [reason] - An optional string with the reason of the leaving - */ - -/** - * The response event for the kick request. - * - * @typedef {object} VIDEOROOM_EVENT_KICKED - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed that has been kicked - */ - -/** - * The response event for the recording enabled request. - * - * @typedef {object} VIDEOROOM_EVENT_RECORDING_ENABLED_STATE - * @property {number|string} room - The involved room - * @property {boolean} recording - Whether or not the room recording is now enabled - */ - -/** - * [multistream] The response event for update subscriber request. - * - * @typedef {object} VIDEOROOM_EVENT_UPDATED - * @property {number|string} room - The involved room - * @property {RTCSessionDescription} [jsep] - The updated JSEP offer - * @property {object[]} streams - List of the updated streams in this subscription - */ - -/** - * The exported plugin descriptor. - * - * @type {object} - * @property {string} id - The plugin identifier used when attaching to Janus - * @property {module:videoroom-plugin~VideoRoomHandle} Handle - The custom class implementing the plugin - * @property {object} EVENT - The events emitted by the plugin - * @property {string} EVENT.VIDEOROOM_PUB_PEER_JOINED {@link module:videoroom-plugin~VIDEOROOM_PUB_PEER_JOINED} - * @property {string} EVENT.VIDEOROOM_PUB_LIST {@link module:videoroom-plugin~VIDEOROOM_PUB_LIST} - * @property {string} EVENT.VIDEOROOM_DESTROYED {@link module:videoroom-plugin~VIDEOROOM_DESTROYED} - * @property {string} EVENT.VIDEOROOM_UNPUBLISHED {@link module:videoroom-plugin~VIDEOROOM_UNPUBLISHED} - * @property {string} EVENT.VIDEOROOM_LEAVING {@link module:videoroom-plugin~VIDEOROOM_LEAVING} - * @property {string} EVENT.VIDEOROOM_DISPLAY {@link module:videoroom-plugin~VIDEOROOM_DISPLAY} - * @property {string} EVENT.VIDEOROOM_KICKED {@link module:videoroom-plugin~VIDEOROOM_KICKED} - * @property {string} EVENT.VIDEOROOM_RECORDING_ENABLED_STATE {@link module:videoroom-plugin~VIDEOROOM_RECORDING_ENABLED_STATE} - * @property {string} EVENT.VIDEOROOM_TALKING {@link module:videoroom-plugin~VIDEOROOM_TALKING} - * @property {string} EVENT.VIDEOROOM_ERROR {@link module:videoroom-plugin~VIDEOROOM_ERROR} - */ -export default { - id: PLUGIN_ID, - Handle: VideoRoomHandle, - EVENT: { - /** - * A peer has joined theh room (notify-joining). - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_PUB_PEER_JOINED - * @type {object} - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed identifier that joined - * @property {string} display - The display name of the peer - */ - VIDEOROOM_PUB_PEER_JOINED: PLUGIN_EVENT.PUB_PEER_JOINED, - - /** - * Active publishers list updated. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_PUB_LIST - * @type {object} - * @property {number|string} room - The involved room - * @property {number|string} feed - The current feed identifier - * @property {object[]} publishers - List of the new publishers - * @property {number|string} publishers[].feed - Feed identifier of the new publisher - * @property {string} publishers[].display - Display name of the new publisher - * @property {boolean} [publishers[].talking] - Whether the publisher is talking or not - * @property {string} [publishers[].audiocodec] - The audio codec used by active publisher - * @property {string} [publishers[].videocodec] - The video codec used by active publisher - * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) - * @property {object[]} [publishers[].streams] - [multistream] Streams description - */ - VIDEOROOM_PUB_LIST: PLUGIN_EVENT.PUB_LIST, - - /** - * The videoroom has been destroyed. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DESTROYED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_DESTROYED} - */ - VIDEOROOM_DESTROYED: PLUGIN_EVENT.DESTROYED, - - /** - * A feed has been unpublished. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UNPUBLISHED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_UNPUBLISHED} - */ - VIDEOROOM_UNPUBLISHED: PLUGIN_EVENT.UNPUBLISHED, - - /** - * A peer has left the room. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_LEAVING - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_LEAVING} - */ - VIDEOROOM_LEAVING: PLUGIN_EVENT.LEAVING, - - /** - * A participant has changed the display name. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DISPLAY - * @type {object} - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed of the peer that change display name - * @property {string} display - The new display name of the peer - */ - VIDEOROOM_DISPLAY: PLUGIN_EVENT.DISPLAY, - - /** - * A handle received a configured event. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_CONFIGURED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_CONFIGURED} - */ - VIDEOROOM_CONFIGURED: PLUGIN_EVENT.CONFIGURED, - - /** - * A handle received a slow link notification. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DISPLAY - * @type {object} - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed of the peer that change display name - * @property {number} bitrate - The current bitrate cap for the participant - */ - VIDEOROOM_SLOWLINK: PLUGIN_EVENT.SLOW_LINK, - - /** - * Notify if the current user is talking. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_TALKING - * @type {object} - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed of the peer this talking notification refers to - * @property {boolean} talking - True if the participant is talking - * @property {number} audio_level - The audio level of the participant in the range [0,127] - */ - VIDEOROOM_TALKING: PLUGIN_EVENT.TALKING, - - /** - * A feed has been kicked out. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_KICKED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_KICKED} - */ - VIDEOROOM_KICKED: PLUGIN_EVENT.KICKED, - - /** - * Conference recording has been enabled or disabled. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_RECORDING_ENABLED_STATE - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_RECORDING_ENABLED_STATE} - */ - VIDEOROOM_RECORDING_ENABLED_STATE: PLUGIN_EVENT.RECORDING_ENABLED_STATE, - - /** - * A switch to a different simulcast substream has been completed. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_SUBSTREAM_LAYER - * @type {object} - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed of the peer this notification refers to - * @property {number} sc_substream_layer - The new simuclast substream layer relayed - */ - VIDEOROOM_SC_SUBSTREAM_LAYER: PLUGIN_EVENT.SC_SUBSTREAM_LAYER, - - /** - * A switch to a different number of simulcast temporal layers has been completed. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_TEMPORAL_LAYERS - * @type {object} - * @property {number|string} room - The involved room - * @property {number|string} feed - The feed of the peer this switch notification refers to - * @property {number} sc_temporal_layers - The new number of simuclast teporal layers relayed - */ - VIDEOROOM_SC_TEMPORAL_LAYERS: PLUGIN_EVENT.SC_TEMPORAL_LAYERS, - - /** - * A multistream subscription has been updated. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UPDATED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_UPDATED} - */ - VIDEOROOM_UPDATED: PLUGIN_EVENT.UPDATED, - - /** - * A generic videoroom error. - * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_ERROR - * @type {Error} - */ - VIDEOROOM_ERROR: PLUGIN_EVENT.ERROR, - }, -}; From 69a43b26e17c030dd299967fc6a5613c6a3d014c Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 4 Sep 2023 11:47:48 +0200 Subject: [PATCH 011/114] Fix indentantion --- src/plugins/audiobridge-plugin.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index 723a6f6..f02523f 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -342,18 +342,18 @@ class AudioBridgeHandle extends Handle { if (typeof message_data.resumed != 'undefined') { janode_event.data.feed = message_data.resumed; if (message_data.participants) { - /* Add participants data */ - janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking, suspended }) => { - const peer = { - feed: id, - display, - muted, - setup, - }; - if (typeof talking !== 'undefined') peer.talking = talking; - if (typeof suspended !== 'undefined') peer.suspended = suspended; - return peer; - }); + /* Add participants data */ + janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking, suspended }) => { + const peer = { + feed: id, + display, + muted, + setup, + }; + if (typeof talking !== 'undefined') peer.talking = talking; + if (typeof suspended !== 'undefined') peer.suspended = suspended; + return peer; + }); } janode_event.event = PLUGIN_EVENT.PEER_RESUMED; break; From 7dda199d2a218fea48dad5e1ed1d877add0e2c50 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 4 Sep 2023 15:30:06 +0200 Subject: [PATCH 012/114] Update package-lock files --- examples/audiobridge/package-lock.json | 1012 +++++------------ examples/echotest/package-lock.json | 1012 +++++------------ examples/helloworld/package-lock.json | 2 +- examples/streaming/package-lock.json | 1012 +++++------------ examples/videoroom/package-lock.json | 1012 +++++------------ package-lock.json | 1399 +++--------------------- 6 files changed, 1368 insertions(+), 4081 deletions(-) diff --git a/examples/audiobridge/package-lock.json b/examples/audiobridge/package-lock.json index 889a707..a60d313 100644 --- a/examples/audiobridge/package-lock.json +++ b/examples/audiobridge/package-lock.json @@ -1,6 +1,6 @@ { "name": "janode-audiobridge", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -11,10 +11,10 @@ "socket.io": "^4.2.0" } }, - "node_modules/@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@types/cookie": { "version": "0.4.1", @@ -22,22 +22,25 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/node": { - "version": "16.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz", - "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==" + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" @@ -46,7 +49,7 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/base64id": { "version": "2.0.0", @@ -57,61 +60,71 @@ } }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -119,7 +132,7 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -142,35 +155,39 @@ } }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", + "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -180,33 +197,33 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -227,48 +244,49 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -278,16 +296,16 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -305,24 +323,76 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/iconv-lite": { @@ -337,9 +407,9 @@ } }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -352,7 +422,7 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -360,12 +430,12 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -382,19 +452,19 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -403,12 +473,12 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } @@ -416,15 +486,23 @@ "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -443,7 +521,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -458,11 +536,17 @@ } }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/range-parser": { @@ -474,12 +558,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -488,9 +572,23 @@ } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -498,80 +596,96 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", + "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } }, "node_modules/socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" }, "engines": { @@ -579,9 +693,9 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -600,9 +714,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -621,17 +735,17 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } @@ -651,7 +765,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -659,7 +773,7 @@ "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -667,15 +781,15 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { "node": ">=10.0.0" }, @@ -692,523 +806,5 @@ } } } - }, - "dependencies": { - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "@types/node": { - "version": "16.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz", - "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==" - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", - "requires": { - "@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.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" - }, - "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "requires": {} - } } } diff --git a/examples/echotest/package-lock.json b/examples/echotest/package-lock.json index 2716c23..8eb35fe 100644 --- a/examples/echotest/package-lock.json +++ b/examples/echotest/package-lock.json @@ -1,6 +1,6 @@ { "name": "janode-echotest", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -11,10 +11,10 @@ "socket.io": "^4.2.0" } }, - "node_modules/@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@types/cookie": { "version": "0.4.1", @@ -22,22 +22,25 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/node": { - "version": "16.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz", - "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==" + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" @@ -46,7 +49,7 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/base64id": { "version": "2.0.0", @@ -57,61 +60,71 @@ } }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -119,7 +132,7 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -142,35 +155,39 @@ } }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", + "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -180,33 +197,33 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -227,48 +244,49 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -278,16 +296,16 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -305,24 +323,76 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/iconv-lite": { @@ -337,9 +407,9 @@ } }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -352,7 +422,7 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -360,12 +430,12 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -382,19 +452,19 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -403,12 +473,12 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } @@ -416,15 +486,23 @@ "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -443,7 +521,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -458,11 +536,17 @@ } }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/range-parser": { @@ -474,12 +558,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -488,9 +572,23 @@ } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -498,80 +596,96 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", + "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } }, "node_modules/socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" }, "engines": { @@ -579,9 +693,9 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -600,9 +714,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -621,17 +735,17 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } @@ -651,7 +765,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -659,7 +773,7 @@ "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -667,15 +781,15 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { "node": ">=10.0.0" }, @@ -692,523 +806,5 @@ } } } - }, - "dependencies": { - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "@types/node": { - "version": "16.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz", - "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==" - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", - "requires": { - "@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.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" - }, - "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "requires": {} - } } } diff --git a/examples/helloworld/package-lock.json b/examples/helloworld/package-lock.json index 065b41b..8853fbe 100644 --- a/examples/helloworld/package-lock.json +++ b/examples/helloworld/package-lock.json @@ -1,6 +1,6 @@ { "name": "janode-helloworld", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { diff --git a/examples/streaming/package-lock.json b/examples/streaming/package-lock.json index f3f0d1a..f360a3e 100644 --- a/examples/streaming/package-lock.json +++ b/examples/streaming/package-lock.json @@ -1,6 +1,6 @@ { "name": "janode-streaming", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -11,10 +11,10 @@ "socket.io": "^4.2.0" } }, - "node_modules/@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@types/cookie": { "version": "0.4.1", @@ -22,22 +22,25 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/node": { - "version": "16.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz", - "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==" + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" @@ -46,7 +49,7 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/base64id": { "version": "2.0.0", @@ -57,61 +60,71 @@ } }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -119,7 +132,7 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -142,35 +155,39 @@ } }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", + "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -180,33 +197,33 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -227,48 +244,49 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -278,16 +296,16 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -305,24 +323,76 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/iconv-lite": { @@ -337,9 +407,9 @@ } }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -352,7 +422,7 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -360,12 +430,12 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -382,19 +452,19 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -403,12 +473,12 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } @@ -416,15 +486,23 @@ "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -443,7 +521,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -458,11 +536,17 @@ } }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/range-parser": { @@ -474,12 +558,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -488,9 +572,23 @@ } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -498,80 +596,96 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", + "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } }, "node_modules/socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" }, "engines": { @@ -579,9 +693,9 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -600,9 +714,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -621,17 +735,17 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } @@ -651,7 +765,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -659,7 +773,7 @@ "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -667,15 +781,15 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { "node": ">=10.0.0" }, @@ -692,523 +806,5 @@ } } } - }, - "dependencies": { - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "@types/node": { - "version": "16.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz", - "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==" - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", - "requires": { - "@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.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" - }, - "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "requires": {} - } } } diff --git a/examples/videoroom/package-lock.json b/examples/videoroom/package-lock.json index 2781c7c..efdcae6 100644 --- a/examples/videoroom/package-lock.json +++ b/examples/videoroom/package-lock.json @@ -1,6 +1,6 @@ { "name": "janode-videoroom", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -11,10 +11,10 @@ "socket.io": "^4.2.0" } }, - "node_modules/@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@types/cookie": { "version": "0.4.1", @@ -22,22 +22,25 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/node": { - "version": "16.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz", - "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==" + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" @@ -46,7 +49,7 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/base64id": { "version": "2.0.0", @@ -57,61 +60,71 @@ } }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -119,7 +132,7 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -142,35 +155,39 @@ } }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", + "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -180,33 +197,33 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -227,48 +244,49 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -278,16 +296,16 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -305,24 +323,76 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/iconv-lite": { @@ -337,9 +407,9 @@ } }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -352,7 +422,7 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -360,12 +430,12 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -382,19 +452,19 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -403,12 +473,12 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } @@ -416,15 +486,23 @@ "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -443,7 +521,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -458,11 +536,17 @@ } }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/range-parser": { @@ -474,12 +558,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -488,9 +572,23 @@ } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -498,80 +596,96 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", + "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } }, "node_modules/socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" }, "engines": { @@ -579,9 +693,9 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -600,9 +714,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -621,17 +735,17 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } @@ -651,7 +765,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -659,7 +773,7 @@ "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -667,15 +781,15 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { "node": ">=10.0.0" }, @@ -692,523 +806,5 @@ } } } - }, - "dependencies": { - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "@types/node": { - "version": "16.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz", - "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==" - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", - "requires": { - "@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.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" - }, - "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "requires": {} - } } } diff --git a/package-lock.json b/package-lock.json index 15b37db..29dfc30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "janode", "version": "1.6.7", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -20,16 +20,49 @@ "node": " >=14.13.1 || >=16.0.0" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", + "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -43,15 +76,24 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/js": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" @@ -112,9 +154,9 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -178,15 +220,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -211,18 +244,6 @@ "concat-map": "0.0.1" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -309,18 +330,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -346,48 +355,47 @@ } }, "node_modules/eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", + "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", - "ajv": "^6.10.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-sdsl": "^4.1.4", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -401,9 +409,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -411,53 +419,32 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -467,9 +454,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -514,34 +501,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -555,9 +514,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -580,18 +539,6 @@ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -609,16 +556,17 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.7", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" } }, "node_modules/flatted": { @@ -666,9 +614,9 @@ } }, "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -680,30 +628,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, "node_modules/has-flag": { @@ -716,9 +644,9 @@ } }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { "node": ">= 4" @@ -786,13 +714,13 @@ "node": ">=0.10.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "engines": { - "node": ">=0.12.0" + "node": ">=8" } }, "node_modules/isexe": { @@ -809,12 +737,6 @@ "ws": "*" } }, - "node_modules/js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -827,6 +749,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -839,6 +767,15 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -873,28 +810,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -914,9 +829,9 @@ "dev": true }, "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -934,17 +849,17 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -1019,27 +934,6 @@ "node": ">=8" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -1050,9 +944,9 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, "engines": { "node": ">=6" @@ -1078,18 +972,6 @@ } ] }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -1168,15 +1050,6 @@ "node": ">=8" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1219,18 +1092,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -1256,13 +1117,13 @@ } }, "node_modules/unix-dgram": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.4.tgz", - "integrity": "sha512-7tpK6x7ls7J7pDrrAU63h93R0dVhRbPwiRRCawR10cl+2e1VOvF3bHlVJc6WI1dl/8qk5He673QU+Ogv7bPNaw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.6.tgz", + "integrity": "sha512-AURroAsb73BZ6CdAyMrTk/hYKNj3DuYYEuOaB8bYMOHGKupRNScw90Q5C71tWJc3uE7dIeXRyuwN0xLLq3vDTg==", "hasInstallScript": true, "dependencies": { - "bindings": "^1.3.0", - "nan": "^2.13.2" + "bindings": "^1.5.0", + "nan": "^2.16.0" }, "engines": { "node": ">=0.10.48" @@ -1292,15 +1153,6 @@ "node": ">= 8" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1308,15 +1160,15 @@ "dev": true }, "node_modules/ws": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", - "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -1339,954 +1191,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", - "@humanwhocodes/module-importer": "^1.0.1", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - } - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "requires": {} - }, - "js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "unix-dgram": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.4.tgz", - "integrity": "sha512-7tpK6x7ls7J7pDrrAU63h93R0dVhRbPwiRRCawR10cl+2e1VOvF3bHlVJc6WI1dl/8qk5He673QU+Ogv7bPNaw==", - "requires": { - "bindings": "^1.3.0", - "nan": "^2.13.2" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "ws": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", - "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==", - "requires": {} - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } From 62d5b22cde036bc841ea8a5434febbe4907c09ed Mon Sep 17 00:00:00 2001 From: August Black Date: Mon, 4 Sep 2023 08:53:14 -0600 Subject: [PATCH 013/114] add host_family to startForward (#29) add host_family to startForward --- src/plugins/audiobridge-plugin.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index f796871..17caf44 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -724,6 +724,7 @@ class AudioBridgeHandle extends Handle { * @param {number|string} params.room - The involved room * @param {boolean} [params.always] - Whether silence should be forwarded when the room is empty * @param {string} params.host - The host to forward to + * @param {string} [params.host_family] - ipv4|ipv6; by default, first family returned by DNS request * @param {number} params.audio_port - The port to forward to * @param {number} [params.ssrc] - The SSRC to use to use when forwarding * @param {number} [params.ptype] - The payload type to use to use when forwarding @@ -732,13 +733,14 @@ class AudioBridgeHandle extends Handle { * @param {string} [params.secret] - The optional secret needed to manage the room * @returns {Promise} */ - async startForward({ room, always, host, audio_port, ssrc, ptype, codec, group, secret }) { + async startForward({ room, always, host, host_family, audio_port, ssrc, ptype, codec, group, secret }) { const body = { request: REQUEST_RTP_FWD_START, room, }; if (typeof always === 'boolean') body.always_on = always; if (typeof host === 'string') body.host = host; + if (typeof host_family === 'string') body.host_family = host_family; if (typeof audio_port === 'number') body.port = audio_port; if (typeof ssrc === 'number') body.ssrc = ssrc; if (typeof ptype === 'number') body.ptype = ptype; @@ -1149,4 +1151,4 @@ export default { */ AUDIOBRIDGE_ERROR: PLUGIN_EVENT.ERROR, }, -}; \ No newline at end of file +}; From e7a9d43b37280f9ec72a08cef3ceca6b9a0afb63 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 6 Sep 2023 16:41:50 +0200 Subject: [PATCH 014/114] Add events --- src/plugins/audiobridge-plugin.js | 45 ++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index f02523f..c42313e 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -335,10 +335,15 @@ class AudioBridgeHandle extends Handle { /* A participant has been suspended */ if (typeof message_data.suspended != 'undefined') { janode_event.data.feed = message_data.suspended; - janode_event.event = PLUGIN_EVENT.PEER_SUSPENDED; + if (this.feed === janode_event.data.feed) { + janode_event.event = PLUGIN_EVENT.SUSPENDED; + } + else { + janode_event.event = PLUGIN_EVENT.PEER_SUSPENDED; + } break; } - /* A participant has been resumed */ + /* This handle or another participant has been resumed */ if (typeof message_data.resumed != 'undefined') { janode_event.data.feed = message_data.resumed; if (message_data.participants) { @@ -355,7 +360,12 @@ class AudioBridgeHandle extends Handle { return peer; }); } - janode_event.event = PLUGIN_EVENT.PEER_RESUMED; + if (this.feed === janode_event.data.feed) { + janode_event.event = PLUGIN_EVENT.RESUMED; + } + else { + janode_event.event = PLUGIN_EVENT.PEER_RESUMED; + } break; } @@ -1028,6 +1038,7 @@ class AudioBridgeHandle extends Handle { * @property {boolean} [participants[].muted] - The muted status of the participant * @property {boolean} [participants[].setup] - True if participant PeerConnection is up * @property {boolean} [participants[].talking] - True if participant is talking + * @property {boolean} [participants[].suspended] - True if participant is suspended */ /** @@ -1155,6 +1166,7 @@ class AudioBridgeHandle extends Handle { * @property {string} EVENT.AUDIOBRIDGE_TALKING {@link module:audiobridge-plugin~AUDIOBRIDGE_TALKING} * @property {string} EVENT.AUDIOBRIDGE_PEER_TALKING {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_TALKING} * @property {string} EVENT.AUDIOBRIDGE_PEER_SUSPENDED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_SUSPENDED} + * @property {string} EVENT.AUDIOBRIDGE_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_RESUMED} * @property {string} EVENT.AUDIOBRIDGE_PEER_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_RESUMED} * @property {string} EVENT.AUDIOBRIDGE_ROOM_MUTED {@link module:audiobridge-plugin~AUDIOBRIDGE_ROOM_MUTED} * @property {string} EVENT.AUDIOBRIDGE_ERROR {@link module:audiobridge-plugin~AUDIOBRIDGE_ERROR} @@ -1250,6 +1262,15 @@ export default { */ AUDIOBRIDGE_PEER_TALKING: PLUGIN_EVENT.PEER_TALKING, + /** + * The current user has been suspended. + * + * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_SUSPENDED + * @type {object} + * @property {number|string} room + * @property {number|string} feed + */ + AUDIOBRIDGE_SUSPENDED: PLUGIN_EVENT.SUSPENDED, /** * Notify if a participant has been suspended. * @@ -1270,6 +1291,24 @@ export default { */ AUDIOBRIDGE_PEER_RESUMED: PLUGIN_EVENT.PEER_RESUMED, + + /** + * The current user has been resumed. + * + * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_RESUMED + * @type {object} + * @property {number|string} room + * @property {number|string} feed + * @property {object[]} participants - The list of participants + * @property {number|string} participants[].feed - The participant feed identifier + * @property {string} [participants[].display] - The participant display name + * @property {boolean} [participants[].muted] - The muted status of the participant + * @property {boolean} [participants[].setup] - True if participant PeerConnection is up + * @property {boolean} [participants[].talking] - True if participant is talking + * @property {boolean} [participants[].suspended] - True if participant is suspended + */ + AUDIOBRIDGE_RESUMED: PLUGIN_EVENT.RESUMED, + /** * The room has been muted or not. * From 0114f858932715c27bbd4b509838dbad8add9748 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 6 Sep 2023 17:21:16 +0200 Subject: [PATCH 015/114] Fix events --- src/plugins/audiobridge-plugin.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index c42313e..2a3afb5 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -46,7 +46,9 @@ const PLUGIN_EVENT = { PEER_KICKED: 'audiobridge_peer_kicked', TALKING: 'audiobridge_talking', PEER_TALKING: 'audiobridge_peer_talking', + SUSPENDED: 'audiobridge_suspended', PEER_SUSPENDED: 'audiobridge_peer_suspended', + RESUMED: 'audiobridge_resumed', PEER_RESUMED: 'audiobridge_peer_resumed', EXISTS: 'audiobridge_exists', ROOMS_LIST: 'audiobridge_list', @@ -1165,6 +1167,7 @@ class AudioBridgeHandle extends Handle { * @property {string} EVENT.AUDIOBRIDGE_PEER_LEAVING {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_LEAVING} * @property {string} EVENT.AUDIOBRIDGE_TALKING {@link module:audiobridge-plugin~AUDIOBRIDGE_TALKING} * @property {string} EVENT.AUDIOBRIDGE_PEER_TALKING {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_TALKING} + * @property {string} EVENT.AUDIOBRIDGE_SUSPENDED {@link module:audiobridge-plugin~AUDIOBRIDGE_SUSPENDED} * @property {string} EVENT.AUDIOBRIDGE_PEER_SUSPENDED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_SUSPENDED} * @property {string} EVENT.AUDIOBRIDGE_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_RESUMED} * @property {string} EVENT.AUDIOBRIDGE_PEER_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_RESUMED} @@ -1278,9 +1281,20 @@ export default { * @type {object} * @property {number|string} room * @property {number|string} feed + * @property {string} display */ AUDIOBRIDGE_PEER_SUSPENDED: PLUGIN_EVENT.PEER_SUSPENDED, + /** + * The current user has been resumed. + * + * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_RESUMED + * @type {object} + * @property {number|string} room + * @property {number|string} feed + */ + AUDIOBRIDGE_RESUMED: PLUGIN_EVENT.RESUMED, + /** * Notify if a participant has been resumed. * @@ -1288,6 +1302,7 @@ export default { * @type {object} * @property {number|string} room * @property {number|string} feed + * @property {string} display */ AUDIOBRIDGE_PEER_RESUMED: PLUGIN_EVENT.PEER_RESUMED, From 6691db792a5434259f4b7796ed1035471cde4099 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 6 Sep 2023 17:34:40 +0200 Subject: [PATCH 016/114] Remove duplicate event --- src/plugins/audiobridge-plugin.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index 2a3afb5..befac3e 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -1306,24 +1306,6 @@ export default { */ AUDIOBRIDGE_PEER_RESUMED: PLUGIN_EVENT.PEER_RESUMED, - - /** - * The current user has been resumed. - * - * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_RESUMED - * @type {object} - * @property {number|string} room - * @property {number|string} feed - * @property {object[]} participants - The list of participants - * @property {number|string} participants[].feed - The participant feed identifier - * @property {string} [participants[].display] - The participant display name - * @property {boolean} [participants[].muted] - The muted status of the participant - * @property {boolean} [participants[].setup] - True if participant PeerConnection is up - * @property {boolean} [participants[].talking] - True if participant is talking - * @property {boolean} [participants[].suspended] - True if participant is suspended - */ - AUDIOBRIDGE_RESUMED: PLUGIN_EVENT.RESUMED, - /** * The room has been muted or not. * From 6428da4bf42d81cb5110dd78397bf2ccfd0f06bc Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 29 Sep 2023 11:21:55 +0200 Subject: [PATCH 017/114] Add partial support for videoroom multistream (replaces #17) - Support "streams" and "descriptions" parameters for configure and publish requests - Add "streams" object when a subscriber joins --- src/plugins/videoroom-plugin.js | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 36eeeca..fff846d 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -194,7 +194,7 @@ class VideoRoomHandle extends Handle { if (typeof audio_codec !== 'undefined') pub.audiocodec = audio_codec; if (typeof video_codec !== 'undefined') pub.videocodec = video_codec; if (typeof simulcast !== 'undefined') pub.simulcast = simulcast; - // Multistream + /* [multistream] add streams info for this participant */ if (typeof streams !== 'undefined') pub.streams = streams; return pub; }); @@ -209,6 +209,8 @@ class VideoRoomHandle extends Handle { janode_event.data.feed = message_data.id; janode_event.data.display = message_data.display; + /* [multistream] add streams info to the subscriber joined event */ + if (typeof message_data.streams !== 'undefined') janode_event.data.streams = message_data.streams; janode_event.event = PLUGIN_EVENT.SUB_JOINED; break; @@ -405,7 +407,7 @@ class VideoRoomHandle extends Handle { if (typeof audio_codec !== 'undefined') pub.audiocodec = audio_codec; if (typeof video_codec !== 'undefined') pub.videocodec = video_codec; if (typeof simulcast !== 'undefined') pub.simulcast = simulcast; - // Multistream + /* [multistream] add streams info for this participant */ if (typeof streams !== 'undefined') pub.streams = streams; return pub; }); @@ -642,6 +644,8 @@ class VideoRoomHandle extends Handle { * @param {string} [params.filename] - If recording, the base path/file to use for the recording (publishers only) * @param {boolean} [params.restart] - Set to force a ICE restart * @param {boolean} [params.update] - Set to force a renegotiation + * @param {object[]} [params.streams] - [multistream] The streams object, each stream includes mid, keyframe, send, min_delay, max_delay + * @param {object[]} [params.descriptions] - [multistream] The descriptions object, can define a description for the tracks separately e.g. track mid:0 'Video Camera', track mid:1 'Screen' * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled (subscribers only) * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below (subscribers only) * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled (subscribers only) @@ -649,7 +653,7 @@ class VideoRoomHandle extends Handle { * @param {RTCSessionDescription} [params.jsep] - The JSEP offer (publishers only) * @returns {Promise} */ - async configure({ audio, video, data, bitrate, record, filename, display, restart, update, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, e2ee, jsep }) { + async configure({ audio, video, data, bitrate, record, filename, display, restart, update, streams, descriptions, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, e2ee, jsep }) { const body = { request: REQUEST_CONFIGURE, }; @@ -662,6 +666,8 @@ class VideoRoomHandle extends Handle { if (typeof display === 'string') body.display = display; if (typeof restart === 'boolean') body.restart = restart; if (typeof update === 'boolean') body.update = update; + if (streams && Array.isArray(streams)) body.streams = streams; + if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; @@ -711,11 +717,13 @@ class VideoRoomHandle extends Handle { * @param {number} [params.bitrate] - Bitrate cap * @param {boolean} [params.record] - True to record the feed * @param {string} [params.filename] - If recording, the base path/file to use for the recording + * @param {object[]} [params.streams] - [multistream] The streams object, each stream includes type, mid, description, disabled, simulcast + * @param {object[]} [params.descriptions] - [multistream] The descriptions object, for each stream you can define description * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection * @param {RTCSessionDescription} params.jsep - The JSEP offer * @returns {Promise} */ - async publish({ audio, video, data, bitrate, record, filename, display, e2ee, jsep }) { + async publish({ audio, video, data, bitrate, record, filename, display, streams, descriptions, e2ee, jsep }) { if (typeof jsep === 'object' && jsep && jsep.type !== 'offer') { const error = new Error('jsep must be an offer'); return Promise.reject(error); @@ -730,6 +738,8 @@ class VideoRoomHandle extends Handle { if (typeof record === 'boolean') body.record = record; if (typeof filename === 'string') body.filename = filename; if (typeof display === 'string') body.display = display; + if (streams && Array.isArray(streams)) body.streams = streams; + if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; const response = await this.message(body, jsep).catch(e => { @@ -812,7 +822,7 @@ class VideoRoomHandle extends Handle { if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; - // Multistream + /* [multistream] */ if (typeof autoupdate === 'boolean') body.autoupdate = autoupdate; const response = await this.message(body); @@ -920,6 +930,9 @@ class VideoRoomHandle extends Handle { /** * [multistream] Update a subscription. * + * @param {object[]} subscribe - The array of streams to subscribe + * @param {object[]} unsubscribe - The array of streams to unsubscribe + * * @returns {Promise} */ async update({ subscribe, unsubscribe }) { @@ -1295,7 +1308,7 @@ class VideoRoomHandle extends Handle { * @property {string} [publishers[].audiocodec] - The audio codec used by active publisher * @property {string} [publishers[].videocodec] - The video codec used by active publisher * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) - * @property {object[]} [publishers[].streams] - [multistream] Streams description + * @property {object[]} [publishers[].streams] - [multistream] Streams description as returned by Janus * @property {RTCSessionDescription} [jsep] - The JSEP answer */ @@ -1306,6 +1319,7 @@ class VideoRoomHandle extends Handle { * @property {number|string} room - The involved room * @property {number|string} feed - The published feed identifier * @property {string} display - The published feed display name + * @property {object[]} [streams] - [multistream] Streams description as returned by Janus */ /** @@ -1535,7 +1549,7 @@ export default { * @property {string} [publishers[].audiocodec] - The audio codec used by active publisher * @property {string} [publishers[].videocodec] - The video codec used by active publisher * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) - * @property {object[]} [publishers[].streams] - [multistream] Streams description + * @property {object[]} [publishers[].streams] - [multistream] Streams description as returned by Janus */ VIDEOROOM_PUB_LIST: PLUGIN_EVENT.PUB_LIST, From 7129d849d8f13290ae74e4fd319c34960ee61b78 Mon Sep 17 00:00:00 2001 From: Dota Coach App Date: Fri, 29 Sep 2023 11:38:54 +0200 Subject: [PATCH 018/114] Update package.json (#30) Add main entry point --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 1883a88..99823d1 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "url": "https://github.com/meetecho/janode/issues" }, "license": "ISC", + "main": "./src/janode.js", "exports": { ".": "./src/janode.js", "./plugins/audiobridge": "./src/plugins/audiobridge-plugin.js", From 6f179adca1d947b236922cce75eed5f234d3deed Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 29 Sep 2023 11:43:07 +0200 Subject: [PATCH 019/114] version: bump to v1.6.8 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 29dfc30..2aef3b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.6.7", + "version": "1.6.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.6.7", + "version": "1.6.8", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index 99823d1..943e93d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.6.7", + "version": "1.6.8", "type": "module", "keywords": [ "janus", From 572974c4b47bb3377fd183960bb21727810c05f8 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 11 Oct 2023 10:57:39 +0200 Subject: [PATCH 020/114] handle: add "ice-failed" event management --- src/handle.js | 12 ++++++++++++ src/protocol.js | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/handle.js b/src/handle.js index 53e024d..a689ad4 100644 --- a/src/handle.js +++ b/src/handle.js @@ -262,6 +262,18 @@ class Handle extends EventEmitter { break; } + /* ice-failed event: Janus ICE agent has detected a failure */ + case JANUS.EVENT.ICE_FAILED: { + /** + * The handle has detected an ICE failure. + * + * @event module:handle~Handle#event:HANDLE_ICE_FAILED + * @type {object} + */ + this.emit(JANODE.EVENT.HANDLE_ICE_FAILED, janode_event_data); + break; + } + /* Hangup event: peer connection is down */ /* In this case the janus message has a reason field */ case JANUS.EVENT.HANGUP: { diff --git a/src/protocol.js b/src/protocol.js index 00a0dde..4e328ce 100644 --- a/src/protocol.js +++ b/src/protocol.js @@ -57,6 +57,7 @@ export const JANUS = { EVENT: { EVENT: 'event', DETACHED: 'detached', + ICE_FAILED: 'ice-failed', HANGUP: 'hangup', MEDIA: 'media', TIMEOUT: 'timeout', @@ -89,6 +90,7 @@ export const JANODE = { CONNECTION_CLOSED: 'connection_closed', SESSION_DESTROYED: 'session_destroyed', HANDLE_DETACHED: 'handle_detached', + HANDLE_ICE_FAILED: 'handle_ice_failed', HANDLE_HANGUP: 'handle_hangup', HANDLE_MEDIA: 'handle_media', HANDLE_WEBRTCUP: 'handle_webrtcup', From 2edb33f2231091f3f8c4a356df2719f745473429 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 11 Oct 2023 14:26:23 +0200 Subject: [PATCH 021/114] version: bump to v1.6.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 943e93d..a83bb4f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.6.8", + "version": "1.6.9", "type": "module", "keywords": [ "janus", From 09d0523288c437da2b76e884dee0fec2a7a9c90a Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 3 Nov 2023 12:44:03 +0100 Subject: [PATCH 022/114] Fix some jsdoc errors --- src/handle.js | 2 +- src/plugins/echotest-plugin.js | 2 +- src/tmanager.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/handle.js b/src/handle.js index a689ad4..92ac64d 100644 --- a/src/handle.js +++ b/src/handle.js @@ -401,7 +401,7 @@ class Handle extends EventEmitter { * Helper to close a transaction with error. * * @property {string} id - The transaction id - * @property {string} error - The error message + * @property {object} error - The error object * @returns {void} */ closeTransactionWithError(id, error) { diff --git a/src/plugins/echotest-plugin.js b/src/plugins/echotest-plugin.js index ec3bf86..92a029a 100644 --- a/src/plugins/echotest-plugin.js +++ b/src/plugins/echotest-plugin.js @@ -169,7 +169,7 @@ class EchoTestHandle extends Handle { * * @type {object} * @property {string} id - The plugin identifier used when attaching to Janus - * @property {module:audiobridge-plugin~AudioBridgeHandle} Handle - The custom class implementing the plugin + * @property {module:echotest-plugin~EchoTestHandle} Handle - The custom class implementing the plugin * @property {object} EVENT - The events emitted by the plugin * @property {string} EVENT.ECHOTEST_RESULT {@link module:echotest-plugin~ECHOTEST_RESULT} * @property {string} EVENT.ECHOTEST_SLOWLINK {@link module:echotest-plugin~ECHOTEST_SLOWLINK} diff --git a/src/tmanager.js b/src/tmanager.js index c6d2a4c..a084fd7 100644 --- a/src/tmanager.js +++ b/src/tmanager.js @@ -156,7 +156,7 @@ class TransactionManager { * * @param {string} id - The transaction identifier * @param {object} owner - A reference to the transaction owner - * @param {string} error - The error string + * @param {object} error - The error object * @returns {PendingTransaction|void} The closed transaction, or nothing if the id does not exist or the owner does not match */ closeTransactionWithError(id, owner, error) { @@ -175,7 +175,7 @@ class TransactionManager { * The closed transactions will be removed from the internal table. * * @param {object} [owner] - A reference to the transaction owner - * @param {string} error - The error string + * @param {object} error - The error object */ closeAllTransactionsWithError(owner, error) { for (const [_, pendingTx] of this.transactions) { From a79e7667b7ea8a532ae40683ce35cc24f1cd090c Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 3 Nov 2023 18:38:28 +0100 Subject: [PATCH 023/114] logger: set default level to "info" if verbosity string is not matched --- src/utils/logger.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/logger.js b/src/utils/logger.js index 22cfb0b..1f95db8 100644 --- a/src/utils/logger.js +++ b/src/utils/logger.js @@ -12,13 +12,15 @@ import { getCliArgument } from './utils.js'; -const LEVELS_IDX = ['none', 'error', 'warn', 'info', 'verb', 'debug'].reduce((obj, lvl, idx) => { +const LEVELS = ['none', 'error', 'warn', 'info', 'verb', 'debug']; +const LEVELS_IDX = LEVELS.reduce((obj, lvl, idx) => { obj[lvl] = idx; return obj; }, {}); const DEFAULT_LEVEL = 'info'; let log_verbosity = getCliArgument('janode-log', 'string', DEFAULT_LEVEL); +if (LEVELS.indexOf(log_verbosity) < 0) log_verbosity = DEFAULT_LEVEL; const printout = (msg_verbosity, console_fn, ...args) => { if (LEVELS_IDX[msg_verbosity] > LEVELS_IDX[log_verbosity]) return; From 1e69ecc1f201abd5b230f541fd3f1acc5e089dbe Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 6 Nov 2023 15:31:51 +0100 Subject: [PATCH 024/114] jsdoc: small fixes --- src/plugins/echotest-plugin.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/echotest-plugin.js b/src/plugins/echotest-plugin.js index 92a029a..cfe4b94 100644 --- a/src/plugins/echotest-plugin.js +++ b/src/plugins/echotest-plugin.js @@ -117,12 +117,12 @@ class EchoTestHandle extends Handle { * Start/update an echotest session. * * @param {object} params - * @param {boolean} [audio] - True to request audio in this session - * @param {boolean} [video] - True to request video in this session - * @param {RTCSessionDescription} [jsep=null] - The JSEP offer - * @param {number} [bitrate=0] - The bitrate to force in the session - * @param {boolean} [record=false] - True to record the session - * @param {string} [filename=null] - The filename of the recording + * @param {boolean} [params.audio] - True to request audio in this session + * @param {boolean} [params.video] - True to request video in this session + * @param {RTCSessionDescription} [params.jsep=null] - The JSEP offer + * @param {number} [params.bitrate=0] - The bitrate to force in the session + * @param {boolean} [params.record=false] - True to record the session + * @param {string} [params.filename=null] - The filename of the recording * @returns {Promise} */ async start({ audio, video, jsep = null, bitrate = 0, record = false, filename = null }) { From 4c6fac69f420a079334a584b2254b40686dfaead Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 8 Nov 2023 15:06:21 +0100 Subject: [PATCH 025/114] package-lock: update --- examples/audiobridge/package-lock.json | 127 ++++++++++++++++++------- examples/echotest/package-lock.json | 127 ++++++++++++++++++------- examples/streaming/package-lock.json | 127 ++++++++++++++++++------- examples/videoroom/package-lock.json | 127 ++++++++++++++++++------- package-lock.json | 105 ++++++++++---------- 5 files changed, 432 insertions(+), 181 deletions(-) diff --git a/examples/audiobridge/package-lock.json b/examples/audiobridge/package-lock.json index a60d313..5884c82 100644 --- a/examples/audiobridge/package-lock.json +++ b/examples/audiobridge/package-lock.json @@ -22,17 +22,20 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", + "integrity": "sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/accepts": { "version": "1.3.8", @@ -91,12 +94,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -154,6 +158,19 @@ "ms": "2.0.0" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -185,9 +202,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", - "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", + "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -329,33 +346,47 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "function-bind": "^1.1.1" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": ">= 0.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { @@ -380,6 +411,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -492,9 +534,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -637,6 +679,20 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -762,6 +818,11 @@ "node": ">= 0.6" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/examples/echotest/package-lock.json b/examples/echotest/package-lock.json index 8eb35fe..68d5b1e 100644 --- a/examples/echotest/package-lock.json +++ b/examples/echotest/package-lock.json @@ -22,17 +22,20 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", + "integrity": "sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/accepts": { "version": "1.3.8", @@ -91,12 +94,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -154,6 +158,19 @@ "ms": "2.0.0" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -185,9 +202,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", - "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", + "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -329,33 +346,47 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "function-bind": "^1.1.1" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": ">= 0.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { @@ -380,6 +411,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -492,9 +534,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -637,6 +679,20 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -762,6 +818,11 @@ "node": ">= 0.6" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/examples/streaming/package-lock.json b/examples/streaming/package-lock.json index f360a3e..6b19b3f 100644 --- a/examples/streaming/package-lock.json +++ b/examples/streaming/package-lock.json @@ -22,17 +22,20 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", + "integrity": "sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/accepts": { "version": "1.3.8", @@ -91,12 +94,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -154,6 +158,19 @@ "ms": "2.0.0" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -185,9 +202,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", - "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", + "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -329,33 +346,47 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "function-bind": "^1.1.1" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": ">= 0.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { @@ -380,6 +411,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -492,9 +534,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -637,6 +679,20 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -762,6 +818,11 @@ "node": ">= 0.6" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/examples/videoroom/package-lock.json b/examples/videoroom/package-lock.json index efdcae6..7553a88 100644 --- a/examples/videoroom/package-lock.json +++ b/examples/videoroom/package-lock.json @@ -22,17 +22,20 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", + "integrity": "sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/accepts": { "version": "1.3.8", @@ -91,12 +94,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -154,6 +158,19 @@ "ms": "2.0.0" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -185,9 +202,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", - "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", + "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -329,33 +346,47 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "function-bind": "^1.1.1" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": ">= 0.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { @@ -380,6 +411,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -492,9 +534,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -637,6 +679,20 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -762,6 +818,11 @@ "node": ">= 0.6" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package-lock.json b/package-lock.json index 2aef3b7..f45ea6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.6.8", + "version": "1.6.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.6.8", + "version": "1.6.9", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", @@ -45,18 +45,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", - "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -77,21 +77,21 @@ } }, "node_modules/@eslint/js": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", - "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", + "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -113,9 +113,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@nodelib/fs.scandir": { @@ -153,10 +153,16 @@ "node": ">= 8" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -355,18 +361,19 @@ } }, "node_modules/eslint": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", - "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", + "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.48.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.53.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -556,12 +563,12 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "dev": true, "dependencies": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, @@ -570,9 +577,9 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/fs.realpath": { @@ -614,9 +621,9 @@ } }, "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -768,9 +775,9 @@ "dev": true }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { "json-buffer": "3.0.1" @@ -829,9 +836,9 @@ "dev": true }, "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -944,9 +951,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -1160,9 +1167,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", + "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", "engines": { "node": ">=10.0.0" }, From ed81cb705184a7214748841cc1d5b1852aa9b3ff Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 5 Dec 2023 17:04:10 +0100 Subject: [PATCH 026/114] audiobridge: fix handling of suspended/resumed events --- src/plugins/audiobridge-plugin.js | 85 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index 117c4dd..cf21da8 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -298,14 +298,40 @@ class AudioBridgeHandle extends Handle { } break; } - /* Configuration events for other participants */ - if (typeof message_data.participants !== 'undefined' && message_data.participants.length == 1) { - janode_event.data.feed = message_data.participants[0].id; - if (typeof message_data.participants[0].display === 'string') janode_event.data.display = message_data.participants[0].display; - if (typeof message_data.participants[0].muted !== 'undefined') janode_event.data.muted = message_data.participants[0].muted; - if (typeof message_data.participants[0].setup !== 'undefined') janode_event.data.setup = message_data.participants[0].setup; - if (typeof message_data.participants[0].suspended !== 'undefined') janode_event.data.suspended = message_data.participants[0].suspended; - janode_event.event = PLUGIN_EVENT.PEER_CONFIGURED; + /* This handle or another participant has been resumed */ + if (typeof message_data.resumed != 'undefined') { + janode_event.data.feed = message_data.resumed; + if (message_data.participants) { + /* Add participants data */ + janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking, suspended }) => { + const peer = { + feed: id, + display, + muted, + setup, + }; + if (typeof talking !== 'undefined') peer.talking = talking; + if (typeof suspended !== 'undefined') peer.suspended = suspended; + return peer; + }); + } + if (this.feed === janode_event.data.feed) { + janode_event.event = PLUGIN_EVENT.RESUMED; + } + else { + janode_event.event = PLUGIN_EVENT.PEER_RESUMED; + } + break; + } + /* This handle or another participant has been suspended */ + if (typeof message_data.suspended != 'undefined') { + janode_event.data.feed = message_data.suspended; + if (this.feed === janode_event.data.feed) { + janode_event.event = PLUGIN_EVENT.SUSPENDED; + } + else { + janode_event.event = PLUGIN_EVENT.PEER_SUSPENDED; + } break; } /* Peer leaving confirmation */ @@ -334,43 +360,16 @@ class AudioBridgeHandle extends Handle { } break; } - /* A participant has been suspended */ - if (typeof message_data.suspended != 'undefined') { - janode_event.data.feed = message_data.suspended; - if (this.feed === janode_event.data.feed) { - janode_event.event = PLUGIN_EVENT.SUSPENDED; - } - else { - janode_event.event = PLUGIN_EVENT.PEER_SUSPENDED; - } - break; - } - /* This handle or another participant has been resumed */ - if (typeof message_data.resumed != 'undefined') { - janode_event.data.feed = message_data.resumed; - if (message_data.participants) { - /* Add participants data */ - janode_event.data.participants = message_data.participants.map(({ id, display, muted, setup, talking, suspended }) => { - const peer = { - feed: id, - display, - muted, - setup, - }; - if (typeof talking !== 'undefined') peer.talking = talking; - if (typeof suspended !== 'undefined') peer.suspended = suspended; - return peer; - }); - } - if (this.feed === janode_event.data.feed) { - janode_event.event = PLUGIN_EVENT.RESUMED; - } - else { - janode_event.event = PLUGIN_EVENT.PEER_RESUMED; - } + /* Configuration events for other participants */ + if (typeof message_data.participants !== 'undefined' && message_data.participants.length == 1) { + janode_event.data.feed = message_data.participants[0].id; + if (typeof message_data.participants[0].display === 'string') janode_event.data.display = message_data.participants[0].display; + if (typeof message_data.participants[0].muted !== 'undefined') janode_event.data.muted = message_data.participants[0].muted; + if (typeof message_data.participants[0].setup !== 'undefined') janode_event.data.setup = message_data.participants[0].setup; + if (typeof message_data.participants[0].suspended !== 'undefined') janode_event.data.suspended = message_data.participants[0].suspended; + janode_event.event = PLUGIN_EVENT.PEER_CONFIGURED; break; } - } /* The event has been handled */ From 1b69ed655f317849a3db4acba00ee3374d4b3379 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 16 Jan 2024 10:50:01 +0100 Subject: [PATCH 027/114] audiobridge: add mute/unmute API and expose "configured" as an emitted event (closes #35) --- .../audiobridge/html/audiobridge-client.js | 34 +++++++ examples/audiobridge/src/index.js | 72 +++++++++++++- src/plugins/audiobridge-plugin.js | 99 ++++++++++++++++++- 3 files changed, 197 insertions(+), 8 deletions(-) diff --git a/examples/audiobridge/html/audiobridge-client.js b/examples/audiobridge/html/audiobridge-client.js index c082f4c..aed7963 100644 --- a/examples/audiobridge/html/audiobridge-client.js +++ b/examples/audiobridge/html/audiobridge-client.js @@ -253,6 +253,32 @@ function _listForward({ room = myRoom, secret = 'adminpwd' } = {}) { }); } +function _mutePeer({ room = myRoom, feed = myFeed, secret = 'adminpwd' } = {}) { + let muteData = { + room, + feed, + secret, + }; + + socket.emit('mute-peer', { + data: muteData, + _id: getId(), + }); +} + +function _unmutePeer({ room = myRoom, feed = myFeed, secret = 'adminpwd' } = {}) { + let unmuteData = { + room, + feed, + secret, + }; + + socket.emit('unmute-peer', { + data: unmuteData, + _id: getId(), + }); +} + function _muteRoom({ room = myRoom, secret = 'adminpwd' } = {}) { let muteData = { room, @@ -460,6 +486,14 @@ socket.on('rtp-fwd-list', ({ data }) => { console.log('rtp forwarders list', data); }); +socket.on('peer-muted', ({ data }) => { + console.log('peer muted', data); +}); + +socket.on('peer-unmuted', ({ data }) => { + console.log('peer unmuted', data); +}); + socket.on('room-muted', ({ data }) => { console.log('room muted', data); }); diff --git a/examples/audiobridge/src/index.js b/examples/audiobridge/src/index.js index a334dd3..f34ed5a 100644 --- a/examples/audiobridge/src/index.js +++ b/examples/audiobridge/src/index.js @@ -146,6 +146,10 @@ function initFrontEnd() { replyEvent(socket, 'peer-leaving', evtdata); }); + audioHandle.on(AudioBridgePlugin.EVENT.AUDIOBRIDGE_CONFIGURED, evtdata => { + replyEvent(socket, 'configured', evtdata); + }); + audioHandle.on(AudioBridgePlugin.EVENT.AUDIOBRIDGE_PEER_CONFIGURED, evtdata => { replyEvent(socket, 'peer-configured', evtdata); }); @@ -442,6 +446,66 @@ function initFrontEnd() { } }); + socket.on('suspend-peer', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} suspend-peer received`); + const { _id, data: suspendpeerdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.suspend(suspendpeerdata); + replyEvent(socket, 'peer-suspended', response, _id); + Logger.info(`${LOG_NS} ${remote} peer-suspended sent`); + } catch ({ message }) { + replyError(socket, message, suspendpeerdata, _id); + } + }); + + socket.on('resume-peer', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} resume-peer received`); + const { _id, data: resumepeerdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.resume(resumepeerdata); + replyEvent(socket, 'peer-resumed', response, _id); + Logger.info(`${LOG_NS} ${remote} peer-resumed sent`); + } catch ({ message }) { + replyError(socket, message, resumepeerdata, _id); + } + }); + + socket.on('mute-peer', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} mute-peer received`); + const { _id, data: mutepeerdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.mute(mutepeerdata); + replyEvent(socket, 'peer-muted', response, _id); + Logger.info(`${LOG_NS} ${remote} peer-muted sent`); + } catch ({ message }) { + replyError(socket, message, mutepeerdata, _id); + } + }); + + socket.on('unmute-peer', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} unmute-peer received`); + const { _id, data: unmutepeerdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.unmute(unmutepeerdata); + replyEvent(socket, 'peer-unmuted', response, _id); + Logger.info(`${LOG_NS} ${remote} peer-unmuted sent`); + } catch ({ message }) { + replyError(socket, message, unmutepeerdata, _id); + } + }); + socket.on('mute-room', async (evtdata = {}) => { Logger.info(`${LOG_NS} ${remote} mute-room received`); const { _id, data: mutedata = {} } = evtdata; @@ -479,8 +543,8 @@ function initFrontEnd() { if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; try { - await janodeManagerHandle.suspend(suspendpeerdata); - replyEvent(socket, 'peer-suspended', {}, _id); + const response = await janodeManagerHandle.suspend(suspendpeerdata); + replyEvent(socket, 'peer-suspended', response, _id); Logger.info(`${LOG_NS} ${remote} peer-suspended sent`); } catch ({ message }) { replyError(socket, message, suspendpeerdata, _id); @@ -494,8 +558,8 @@ function initFrontEnd() { if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; try { - await janodeManagerHandle.resume(resumepeerdata); - replyEvent(socket, 'peer-resumed', {}, _id); + const response = await janodeManagerHandle.resume(resumepeerdata); + replyEvent(socket, 'peer-resumed', response, _id); Logger.info(`${LOG_NS} ${remote} peer-resumed sent`); } catch ({ message }) { replyError(socket, message, resumepeerdata, _id); diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index cf21da8..f67b58b 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -28,7 +28,9 @@ const REQUEST_RTP_FWD_STOP = 'stop_rtp_forward'; const REQUEST_RTP_FWD_LIST = 'listforwarders'; const REQUEST_SUSPEND_PARTICIPANT = 'suspend'; const REQUEST_RESUME_PARTICIPANT = 'resume'; -const REQUEST_MUTE_ROOM = 'mute_room'; +const REQUEST_MUTE_PARTICIPANT = 'mute'; +const REQUEST_UNMUTE_PARTICIPANT = 'unmute'; +const REQUEST_MUTE_ROOM = 'unmute_room'; const REQUEST_UNMUTE_ROOM = 'unmute_room'; /* These are the events/responses that the Janode plugin will manage */ @@ -367,7 +369,8 @@ class AudioBridgeHandle extends Handle { if (typeof message_data.participants[0].muted !== 'undefined') janode_event.data.muted = message_data.participants[0].muted; if (typeof message_data.participants[0].setup !== 'undefined') janode_event.data.setup = message_data.participants[0].setup; if (typeof message_data.participants[0].suspended !== 'undefined') janode_event.data.suspended = message_data.participants[0].suspended; - janode_event.event = PLUGIN_EVENT.PEER_CONFIGURED; + /* when using "mute"/"unmute" management requests, janus will notify "configured" to all participants, including the involved one */ + janode_event.event = janode_event.data.feed !== this.feed ? PLUGIN_EVENT.PEER_CONFIGURED : PLUGIN_EVENT.CONFIGURED; break; } } @@ -854,6 +857,64 @@ class AudioBridgeHandle extends Handle { throw (error); } + /** + * Mute an user in the audiobridge. + * + * @param {object} params + * @param {number|string} params.room - The involved room + * @param {number|string} params.feed - The feed to mute + * @param {string} [params.secret] - The optional secret needed for managing the room + * @returns {Promise} + */ + async mute({ room, feed, secret }) { + const body = { + request: REQUEST_MUTE_PARTICIPANT, + room, + id: feed, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.SUCCESS) { + /* Add data missing from Janus response */ + evtdata.room = body.room; + evtdata.feed = body.id; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Unmute an user in the audiobridge. + * + * @param {object} params + * @param {number|string} params.room - The involved room + * @param {number|string} params.feed - The feed to unmute + * @param {string} [params.secret] - The optional secret needed for managing the room + * @returns {Promise} + */ + async unmute({ room, feed, secret }) { + const body = { + request: REQUEST_UNMUTE_PARTICIPANT, + room, + id: feed, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = response._janode || {}; + if (event === PLUGIN_EVENT.SUCCESS) { + /* Add data missing from Janus response */ + evtdata.room = body.room; + evtdata.feed = body.id; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + /** * Mute the given room for every participant. * @@ -1116,14 +1177,30 @@ class AudioBridgeHandle extends Handle { */ /** - * The response event for audiobridge mute request. + * The response event for audiobridge mute participant request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_MUTE_PARTICIPANT_RESPONSE + * @property {number|string} room - The involved room + * @property {number|string} feed - The involved feed id + */ + +/** + * The response event for audiobridge unmute participant request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_UNMUTE_PARTICIPANT_RESPONSE + * @property {number|string} room - The involved room + * @property {number|string} feed - The involved feed id + */ + +/** + * The response event for audiobridge mute room request. * * @typedef {object} AUDIOBRIDGE_EVENT_MUTE_ROOM_RESPONSE * @property {number|string} room - The involved room */ /** - * The response event for audiobridge unmute request. + * The response event for audiobridge unmute room request. * * @typedef {object} AUDIOBRIDGE_EVENT_UNMUTE_ROOM_RESPONSE * @property {number|string} room - The involved room @@ -1161,6 +1238,7 @@ class AudioBridgeHandle extends Handle { * @property {module:audiobridge-plugin~AudioBridgeHandle} Handle - The custom class implementing the plugin * @property {object} EVENT - The events emitted by the plugin * @property {string} EVENT.AUDIOBRIDGE_DESTROYED {@link module:audiobridge-plugin~AUDIOBRIDGE_DESTROYED} + * @property {string} EVENT.AUDIOBRIDGE_CONFIGURED {@link module:audiobridge-plugin~AUDIOBRIDGE_CONFIGURED} * @property {string} EVENT.AUDIOBRIDGE_KICKED - {@link module:audiobridge-plugin~AUDIOBRIDGE_KICKED} * @property {string} EVENT.AUDIOBRIDGE_PEER_JOINED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_JOINED} * @property {string} EVENT.AUDIOBRIDGE_PEER_CONFIGURED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_CONFIGURED} @@ -1188,6 +1266,19 @@ export default { */ AUDIOBRIDGE_DESTROYED: PLUGIN_EVENT.DESTROYED, + /** + * The current user has been configured. + * + * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_CONFIGURED + * @type {object} + * @property {number|string} room + * @property {number|string} feed + * @property {string} [display] + * @property {boolean} [muted] + * @property {boolean} [setup] + */ + AUDIOBRIDGE_CONFIGURED: PLUGIN_EVENT.CONFIGURED, + /** * The current user has been kicked out. * From 1f61f19da4f8c866f92fe4dce2be1f5243e0fbf1 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 22 Jan 2024 13:52:31 +0100 Subject: [PATCH 028/114] logger: change how verbosity is being set internally --- src/utils/logger.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/utils/logger.js b/src/utils/logger.js index 1f95db8..66e0521 100644 --- a/src/utils/logger.js +++ b/src/utils/logger.js @@ -12,7 +12,7 @@ import { getCliArgument } from './utils.js'; -const LEVELS = ['none', 'error', 'warn', 'info', 'verb', 'debug']; +const LEVELS = ['none', 'error', 'warning', 'info', 'verbose', 'debug']; const LEVELS_IDX = LEVELS.reduce((obj, lvl, idx) => { obj[lvl] = idx; return obj; @@ -20,7 +20,6 @@ const LEVELS_IDX = LEVELS.reduce((obj, lvl, idx) => { const DEFAULT_LEVEL = 'info'; let log_verbosity = getCliArgument('janode-log', 'string', DEFAULT_LEVEL); -if (LEVELS.indexOf(log_verbosity) < 0) log_verbosity = DEFAULT_LEVEL; const printout = (msg_verbosity, console_fn, ...args) => { if (LEVELS_IDX[msg_verbosity] > LEVELS_IDX[log_verbosity]) return; @@ -49,7 +48,7 @@ const Logger = { * @function * @param {...any} args */ - verbose: (...args) => printout('verb', console.debug, ...args), + verbose: (...args) => printout('verbose', console.debug, ...args), /** * Info logging (default). @@ -67,7 +66,7 @@ const Logger = { * @function * @param {...any} args */ - warn: (...args) => printout('warn', console.warn, ...args), + warning: (...args) => printout('warning', console.warn, ...args), /** * Error logging. @@ -87,11 +86,21 @@ const Logger = { */ setLevel: (lvl = '') => { lvl = lvl.toLowerCase(); - if (lvl === 'verbose') lvl = 'verb'; - if (lvl === 'warning') lvl = 'warn'; - if (typeof LEVELS_IDX[lvl] === 'number') log_verbosity = lvl; + if (lvl === 'verb') lvl = 'verbose'; + if (lvl === 'warn') lvl = 'warning'; + if (typeof LEVELS_IDX[lvl] === 'number') { + log_verbosity = lvl; + } + else { + log_verbosity = DEFAULT_LEVEL; + } return log_verbosity; } }; +/* set aliases */ +Logger.verb = Logger.verbose; +Logger.warn = Logger.warning; + +Logger.setLevel(log_verbosity); export default Logger; \ No newline at end of file From bf2d989479f4c90c6bd043d442c736dc46d421d5 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 22 Jan 2024 13:54:32 +0100 Subject: [PATCH 029/114] logger: increase padding --- src/utils/logger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/logger.js b/src/utils/logger.js index 66e0521..7034b23 100644 --- a/src/utils/logger.js +++ b/src/utils/logger.js @@ -24,7 +24,7 @@ let log_verbosity = getCliArgument('janode-log', 'string', DEFAULT_LEVEL); const printout = (msg_verbosity, console_fn, ...args) => { if (LEVELS_IDX[msg_verbosity] > LEVELS_IDX[log_verbosity]) return; const ts = (new Date()).toISOString(); - const prefix = `${ts} - ${msg_verbosity.toUpperCase().padEnd(5, ' ')}:`; + const prefix = `${ts} - ${msg_verbosity.toUpperCase().padEnd(8, ' ')}:`; console_fn(prefix, ...args); }; From b6eb92a47984dbd4d004da231b546cb2c14eeb3a Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 26 Jan 2024 13:36:03 +0100 Subject: [PATCH 030/114] videoroom/streaming: add support to e2ee --- src/plugins/streaming-plugin.js | 6 +++++- src/plugins/videoroom-plugin.js | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index f90dfe4..d2c8b66 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -94,6 +94,7 @@ class StreamingHandle extends Handle { /* Add JSEP data if available */ if (jsep) janode_event.data.jsep = jsep; + if (jsep && typeof jsep.e2ee === 'boolean') janode_event.data.e2ee = jsep.e2ee; /* The plugin will emit an event only if the handle does not own the transaction */ /* That means that a transaction has already been closed or this is an async event */ @@ -527,6 +528,7 @@ class StreamingHandle extends Handle { * @param {string} [params.pin] - The pin that'll be needed to connect to the new mountpoint * @param {boolean} [params.permanent=false] - True if Janus must persist the mp on a config file * @param {boolean} [params.is_private=false] - Flag the mp as private + * @param {boolean} [params.e2ee=false] - True to set a a mp as end to end encrypted * @param {object} [params.audio] - The audio descriptor for the mp * @param {number} [params.audio.port] - Port used for audio RTP * @param {number} [params.audio.rtcpport] - Port used for audio RTCP @@ -550,13 +552,14 @@ class StreamingHandle extends Handle { * @param {object} [params.metadata] - An opaque metadata to add to the mp * @returns {Promise} */ - async createRtpMountpoint({ id = 0, name, description, secret, pin, permanent = false, is_private = false, audio, video, data, threads, metadata }) { + async createRtpMountpoint({ id = 0, name, description, secret, pin, permanent = false, is_private = false, e2ee = false, audio, video, data, threads, metadata }) { const body = { request: REQUEST_CREATE, type: 'rtp', id, permanent, is_private, + e2ee, audio: false, video: false, data: false, @@ -682,6 +685,7 @@ class StreamingHandle extends Handle { * @property {string} status - The current status of the stream * @property {number|string} [id] - The involved mountpoint identifier * @property {boolean} [restart] - True if the request had it true + * @property {boolean} [e2ee] - True if an offered stream is end to end encrypted * @property {RTCSessionDescription} [jsep] - Optional JSEP offer from Janus */ diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index fff846d..f7f1ca6 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -1309,6 +1309,7 @@ class VideoRoomHandle extends Handle { * @property {string} [publishers[].videocodec] - The video codec used by active publisher * @property {boolean} publishers[].simulcast - True if the publisher uses simulcast (VP8 and H.264 only) * @property {object[]} [publishers[].streams] - [multistream] Streams description as returned by Janus + * @property {boolean} [e2ee] - True if the stream is end-to-end encrypted * @property {RTCSessionDescription} [jsep] - The JSEP answer */ @@ -1428,6 +1429,7 @@ class VideoRoomHandle extends Handle { * @property {boolean} [restart] - True if the request had it true * @property {boolean} [update] - True if the request had it true * @property {string} configured - A string with the value returned by Janus + * @property {boolean} [e2ee] - True if the stream is end-to-end encrypted * @property {RTCSessionDescription} [jsep] - The JSEP answer */ From c8247f7ef97da67228b121f54a63572cb28578e9 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 26 Jan 2024 15:55:28 +0100 Subject: [PATCH 031/114] videoroom/streaming: add optional e2ee parameter to start request --- src/plugins/streaming-plugin.js | 4 +++- src/plugins/videoroom-plugin.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index d2c8b66..1702dc0 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -248,9 +248,10 @@ class StreamingHandle extends Handle { * * @param {object} params * @property {RTCSessionDescription} params.jsep + * @property {boolean} [params.e2ee] * @returns {Promise} */ - async start({ jsep }) { + async start({ jsep, e2ee }) { if (typeof jsep === 'object' && jsep && jsep.type !== 'answer') { const error = new Error('jsep must be an answer'); return Promise.reject(error); @@ -259,6 +260,7 @@ class StreamingHandle extends Handle { const body = { request: REQUEST_START, }; + jsep.e2ee = (typeof e2ee === 'boolean') ? e2ee : jsep.e2ee; const response = await this.message(body, jsep); const { event, data: evtdata } = response._janode || {}; diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index f7f1ca6..2267bbf 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -847,12 +847,14 @@ class VideoRoomHandle extends Handle { * * @param {object} params * @param {RTCSessionDescription} params.jsep - The JSEP answer + * @param {boolean} [e2ee] - True to hint an end-to-end encrypted negotiation * @returns {Promise} */ - async start({ jsep }) { + async start({ jsep, e2ee }) { const body = { request: REQUEST_START, }; + jsep.e2ee = (typeof e2ee === 'boolean') ? e2ee : jsep.e2ee; const response = await this.message(body, jsep); const { event, data: evtdata } = response._janode || {}; From d4f11968d842ca3aa916db49057216fca51f4820 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 31 Jan 2024 12:48:18 +0100 Subject: [PATCH 032/114] streaming: enhance simulcast support --- examples/streaming/html/streaming-client.js | 40 +++++++++++++-------- examples/streaming/src/index.js | 4 --- src/plugins/streaming-plugin.js | 25 +++++++++---- 3 files changed, 44 insertions(+), 25 deletions(-) diff --git a/examples/streaming/html/streaming-client.js b/examples/streaming/html/streaming-client.js index 033d2db..4dc1f48 100644 --- a/examples/streaming/html/streaming-client.js +++ b/examples/streaming/html/streaming-client.js @@ -1,3 +1,4 @@ +/* eslint-disable multiline-comment-style */ /* global io */ 'use strict'; @@ -86,12 +87,15 @@ function _stop() { }); } -function _configure({ audio, video, data }) { +function _configure({ audio, video, data, substream, temporal, fallback }) { socket.emit('configure', { data: { audio, video, data, + substream, + temporal, + fallback, }, _id: getId(), }); @@ -164,7 +168,7 @@ function _stopRec({ id = myStream, secret = 'adminpwd' } = {}) { }); } -function _createMp({ aport, vport, secret = null, pin = null }) { +function _createMp({ audio, video, data, secret = null, pin = null } = {}) { const settings = {}; settings.name = 'test_opus_vp8_' + Date.now(); settings.description = 'this is ' + settings.name; @@ -172,18 +176,26 @@ function _createMp({ aport, vport, secret = null, pin = null }) { settings.pin = pin || null; settings.permanent = false; settings.is_private = false; - settings.audio = { - port: aport, - pt: 111, - rtpmap: 'opus/48000/2', - }; - settings.video = { - port: vport, - pt: 100, - rtpmap: 'VP8/90000', - buffer: true, - }; - settings.data = {}; + if (audio) { + settings.audio = typeof audio === 'object' ? audio : {}; + settings.audio.port = settings.audio.port || 0; + settings.audio.pt = settings.audio.pt || 111; + settings.audio.rtpmap = settings.audio.rtpmap || 'opus/48000/2'; + } + if (video) { + settings.video = typeof video === 'object' ? video : {}; + settings.video.port = settings.video.port || 0; + //settings.video.port2 = settings.video.port2 || 0; + //settings.video.port3 = settings.video.port3 || 0; + //setting.video.rtcpport = setting.video.rtcpport || 0; + settings.video.pt = settings.video.pt || 100; + settings.video.rtpmap = settings.video.rtpmap || 'VP8/90000'; + //settings.video.buffer = settings.video.buffer || false; + } + if (data) { + settings.data = typeof data === 'object' ? data : {}; + //settings.data.buffer = settings.data.buffer || false; + } socket.emit('create', { data: settings, _id: getId(), diff --git a/examples/streaming/src/index.js b/examples/streaming/src/index.js index 7d9988d..94a6aca 100644 --- a/examples/streaming/src/index.js +++ b/examples/streaming/src/index.js @@ -369,10 +369,6 @@ function initFrontEnd() { if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; - mpdata.audio = (typeof mpdata.audio === 'object' && mpdata.audio) ? mpdata.audio : null; - mpdata.video = (typeof mpdata.video === 'object' && mpdata.video) ? mpdata.video : null; - mpdata.data = (typeof mpdata.data === 'object' && mpdata.data) ? mpdata.data : null; - try { const created = await janodeManagerHandle.createRtpMountpoint(mpdata); replyEvent(socket, 'created', created, _id); diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index 1702dc0..5f6145e 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -132,6 +132,8 @@ class StreamingHandle extends Handle { janode_event.data.audio_port = (message_data.stream) ? message_data.stream.audio_port : null; janode_event.data.audio_rtcp_port = (message_data.stream) ? message_data.stream.audio_rtcp_port : null; janode_event.data.video_port = (message_data.stream) ? message_data.stream.video_port : null; + janode_event.data.video_port_2 = (message_data.stream) ? message_data.stream.video_port_2 : null; + janode_event.data.video_port_3 = (message_data.stream) ? message_data.stream.video_port_3 : null; janode_event.data.video_rtcp_port = (message_data.stream) ? message_data.stream.video_rtcp_port : null; janode_event.data.data_port = (message_data.stream) ? message_data.stream.data_port : null; break; @@ -540,6 +542,8 @@ class StreamingHandle extends Handle { * @param {boolean} [params.audio.skew] - Set skew compensation * @param {object} [params.video] - The video descriptor for the mp * @param {number} [params.video.port] - Port used for video RTP + * @param {number} [params.video.port2] - Port used for video RTP (simulcast layer) + * @param {number} [params.video.port3] - Port used for video RTP (simulcast layer) * @param {number} [params.video.rtcpport] - Port used for video RTCP * @param {string} [params.video.mcast] - Multicast address to listen to * @param {number} [params.video.pt] - Payload type that will be used @@ -573,28 +577,33 @@ class StreamingHandle extends Handle { if (typeof pin === 'string') body.pin = pin; if (typeof audio === 'object' && audio) { body.audio = true; - if (typeof audio.port === 'number') body.audioport = audio.port; + body.audioport = (typeof audio.port === 'number') ? audio.port : 0; if (typeof audio.rtcpport === 'number') body.audiortcpport = audio.rtcppport; if (typeof audio.mcast === 'string') body.audiomcast = audio.mcast; if (audio.pt) body.audiopt = audio.pt; if (audio.rtpmap) body.audiortpmap = audio.rtpmap; - if (audio.skew) body.audioskew = audio.skew || false; + if (typeof audio.skew === 'boolean') body.audioskew = audio.skew; } if (typeof video === 'object' && video) { body.video = true; - if (typeof video.port === 'number') body.videoport = video.port; + body.videoport = (typeof video.port === 'number') ? video.port : 0; if (typeof video.rtcpport === 'number') body.videortcpport = video.rtcpport; if (typeof video.mcast === 'string') body.videomcast = video.mcast; if (video.pt) body.videopt = video.pt; if (video.rtpmap) body.videortpmap = video.rtpmap; if (video.fmtp) body.videofmtp = video.fmtp; - if (video.buffer) body.videobufferkf = video.buffer || false; - if (video.skew) body.videoskew = video.skew || false; + if (typeof video.buffer === 'boolean') body.videobufferkf = video.buffer; + if (typeof video.skew === 'boolean') body.videoskew = video.skew; + if (typeof video.port2 === 'number' && typeof video.port3 === 'number') { + body.videosimulcast = true; + body.videoport2 = video.port2; + body.videoport3 = video.port3; + } } if (typeof data === 'object' && data) { body.data = true; - body.dataport = data.port || 0; - if (data.buffer) body.databuffermsg = data.buffer || false; + body.dataport = (typeof data.port === 'number') ? data.port : 0; + if (typeof data.buffer === 'boolean') body.databuffermsg = data.buffer; } if (typeof threads === 'number' && threads > 0) body.threads = threads; if (metadata) body.metadata = metadata; @@ -669,6 +678,8 @@ class StreamingHandle extends Handle { * @property {number} [audio_port] - The port for RTP audio * @property {number} [audio_rtcp_port] - The port RTCP audio * @property {number} [video_port] - The port for RTP video + * @property {number} [video_port_2] - The port for RTP video (simulcast) + * @property {number} [video_port_3] - The port for RTP video (simulcast) * @property {number} [video_rtcp_port] - The port for RTCP video * @property {number} [data_port] - The port for datachannels */ From c9f5014ddef470ecfb9662f163a1dc5d5e9fffe0 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 31 Jan 2024 13:17:29 +0100 Subject: [PATCH 033/114] package.lock: update dependencies --- package-lock.json | 76 +++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index f45ea6e..93c5170 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,9 +54,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -77,22 +77,22 @@ } }, "node_modules/@eslint/js": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", - "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -113,9 +113,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@nodelib/fs.scandir": { @@ -160,9 +160,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -361,15 +361,15 @@ } }, "node_modules/eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", - "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.53.0", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -521,9 +521,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -563,9 +563,9 @@ } }, "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { "flatted": "^3.2.9", @@ -573,7 +573,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -621,9 +621,9 @@ } }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -651,9 +651,9 @@ } }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -1167,9 +1167,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { "node": ">=10.0.0" }, From a061b809a500f62b9b813953b12f7d9751fe096b Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 31 Jan 2024 13:18:24 +0100 Subject: [PATCH 034/114] version: bump to v1.6.10 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93c5170..6da4f98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "janode", - "version": "1.6.9", + "version": "1.6.10", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index a83bb4f..7059f4c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.6.9", + "version": "1.6.10", "type": "module", "keywords": [ "janus", From 8e9e6ef55ef07a71ef3ce1f81e5ebce29c4755c4 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 31 Jan 2024 14:18:31 +0100 Subject: [PATCH 035/114] package.json: fix as suggested by npm --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7059f4c..9aa4051 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/meetecho/janode.git" + "url": "git+https://github.com/meetecho/janode.git" }, "bugs": { "url": "https://github.com/meetecho/janode/issues" @@ -48,6 +48,6 @@ }, "scripts": { "build": "npm install --omit=dev", - "lint": "node_modules/.bin/eslint --ext .js --config .eslintrc.json src" + "lint": "eslint --ext .js --config .eslintrc.json src" } } From 1b7f51cc511c7b0c1d5fb05ab52ae102c6bbd7ec Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 31 Jan 2024 18:57:13 +0100 Subject: [PATCH 036/114] videoroom: add "streams" parsing to "configured" event --- src/plugins/videoroom-plugin.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 2267bbf..d47524d 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -417,6 +417,8 @@ class VideoRoomHandle extends Handle { if (typeof message_data.configured !== 'undefined') { janode_event.event = PLUGIN_EVENT.CONFIGURED; janode_event.data.feed = this.feed; + /* [multistream] add streams info */ + if (typeof streams !== 'undefined') janode_event.data.streams = message_data.streams; janode_event.data.configured = message_data.configured; break; } From 571587f0a46a4b5383add0ebecbf1dad2829bcb4 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 31 Jan 2024 18:58:05 +0100 Subject: [PATCH 037/114] Fix unneeded space --- src/plugins/videoroom-plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index d47524d..426a42e 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -418,7 +418,7 @@ class VideoRoomHandle extends Handle { janode_event.event = PLUGIN_EVENT.CONFIGURED; janode_event.data.feed = this.feed; /* [multistream] add streams info */ - if (typeof streams !== 'undefined') janode_event.data.streams = message_data.streams; + if (typeof streams !== 'undefined') janode_event.data.streams = message_data.streams; janode_event.data.configured = message_data.configured; break; } From dd722fd206fe8d264ed95ed367a29ab749e78cd8 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 31 Jan 2024 18:59:06 +0100 Subject: [PATCH 038/114] jsdoc: update --- src/plugins/videoroom-plugin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 426a42e..ca4354a 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -1433,6 +1433,7 @@ class VideoRoomHandle extends Handle { * @property {boolean} [restart] - True if the request had it true * @property {boolean} [update] - True if the request had it true * @property {string} configured - A string with the value returned by Janus + * @property {object[]} [streams] - [multistream] Streams description as returned by Janus * @property {boolean} [e2ee] - True if the stream is end-to-end encrypted * @property {RTCSessionDescription} [jsep] - The JSEP answer */ From 1c07148a41266f5c377c13654974e70cf9c324a3 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 31 Jan 2024 19:11:41 +0100 Subject: [PATCH 039/114] jsdoc: update --- src/plugins/videoroom-plugin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index ca4354a..ddf8a44 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -1444,6 +1444,7 @@ class VideoRoomHandle extends Handle { * @typedef {object} VIDEOROOM_EVENT_STARTED * @property {number|string} room - The involved room * @property {number|string} feed - The feed that started + * @property {boolean} [e2ee] - True if started stream is e2ee * @property {string} started - A string with the value returned by Janus */ From 6387379d4cb5e37782d89b1e04b5aa9a4f9ae254 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 2 Feb 2024 12:40:07 +0100 Subject: [PATCH 040/114] videoroom: fix "streams" parsing in configured event --- src/plugins/videoroom-plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index ddf8a44..9e745ab 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -418,7 +418,7 @@ class VideoRoomHandle extends Handle { janode_event.event = PLUGIN_EVENT.CONFIGURED; janode_event.data.feed = this.feed; /* [multistream] add streams info */ - if (typeof streams !== 'undefined') janode_event.data.streams = message_data.streams; + if (typeof message_data.streams !== 'undefined') janode_event.data.streams = message_data.streams; janode_event.data.configured = message_data.configured; break; } From 6432967eac37d9f0ba9cebda9bb0dc3cff60d2e7 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 6 Feb 2024 15:42:45 +0100 Subject: [PATCH 041/114] videoroom: support simulcast ports for startForward and fix listForward --- src/plugins/videoroom-plugin.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 9e745ab..693b3a8 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -261,6 +261,14 @@ class VideoRoomHandle extends Handle { janode_event.data.forwarder.video_port = message_data.rtp_stream.video; janode_event.data.forwarder.video_rtcp_port = message_data.rtp_stream.video_rtcp; janode_event.data.forwarder.video_stream = message_data.rtp_stream.video_stream_id; + if (message_data.rtp_stream.video_stream_id_2) { + janode_event.data.forwarder.video_port_2 = message_data.rtp_stream.video_2; + janode_event.data.forwarder.video_stream_2 = message_data.rtp_stream.video_stream_id_2; + } + if (message_data.rtp_stream.video_stream_id_3) { + janode_event.data.forwarder.video_port_3 = message_data.rtp_stream.video_3; + janode_event.data.forwarder.video_stream_3 = message_data.rtp_stream.video_stream_id_3; + } } if (message_data.rtp_stream.data) { janode_event.data.forwarder.data_port = message_data.rtp_stream.data; @@ -278,7 +286,7 @@ class VideoRoomHandle extends Handle { /* RTP forwarders list */ case 'forwarders': - if (janode_event.data.forwarders) { + if (message_data.rtp_forwarders) { janode_event.data.forwarders = message_data.rtp_forwarders.map(({ publisher_id, rtp_forwarder }) => { const pub = { feed: publisher_id, @@ -310,7 +318,7 @@ class VideoRoomHandle extends Handle { return pub; }); } - else if (janode_event.data.publishers) { + else if (message_data.publishers) { janode_event.data.forwarders = message_data.publishers.map(({ publisher_id, forwarders }) => { const pub = { feed: publisher_id, @@ -1206,12 +1214,16 @@ class VideoRoomHandle extends Handle { * @param {number} [params.video_port] - The target video RTP port, if video is to be forwarded * @param {number} [params.video_rtcp_port] - The target video RTCP port, if video is to be forwarded * @param {number} [params.video_ssrc] - The SSRC that will be used for video RTP + * @param {number} [params.video_port_2] - The target video RTP port for simulcast substream + * @param {number} [params.video_ssrc_2] - The SSRC that will be used for video RTP substream + * @param {number} [params.video_port_3] - The target video RTP port for simulcast substream + * @param {number} [params.video_ssrc_3] - The SSRC that will be used for video RTP substream * @param {number} [params.data_port] - The target datachannels port, if datachannels are to be forwarded * @param {string} [params.secret] - The secret needed for managing the room * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ - async startForward({ room, feed, host, audio_port, audio_rtcp_port, audio_ssrc, video_port, video_rtcp_port, video_ssrc, data_port, secret, admin_key }) { + async startForward({ room, feed, host, audio_port, audio_rtcp_port, audio_ssrc, video_port, video_rtcp_port, video_ssrc, video_port_2, video_ssrc_2, video_port_3, video_ssrc_3, data_port, secret, admin_key }) { const body = { request: REQUEST_RTP_FWD_START, room, @@ -1224,6 +1236,10 @@ class VideoRoomHandle extends Handle { if (typeof video_port === 'number') body.video_port = video_port; if (typeof video_rtcp_port === 'number') body.video_rtcp_port = video_rtcp_port; if (typeof video_ssrc === 'number') body.video_ssrc = video_ssrc; + if (typeof video_port_2 === 'number') body.video_port_2 = video_port_2; + if (typeof video_ssrc_2 === 'number') body.video_ssrc_2 = video_ssrc_2; + if (typeof video_port_3 === 'number') body.video_port_3 = video_port_3; + if (typeof video_ssrc_3 === 'number') body.video_ssrc_3 = video_ssrc_3; if (typeof data_port === 'number') body.data_port = data_port; if (typeof secret === 'string') body.secret = secret; if (typeof admin_key === 'string') body.admin_key = admin_key; @@ -1374,6 +1390,10 @@ class VideoRoomHandle extends Handle { * @property {number} [video_port] - The RTP video target port * @property {number} [video_rtcp_port] - The RTCP video target port * @property {number} [video_stream] - The video forwarder identifier + * @property {number} [video_port_2] - The RTP video target port (simulcast) + * @property {number} [video_stream_2] - The video forwarder identifier (simulcast) + * @property {number} [video_port_3] - The RTP video target port (simulcast) + * @property {number} [video_stream_3] - The video forwarder identifier (simulcast) * @property {number} [data_port] - The datachannels target port * @property {number} [data_stream] - The datachannels forwarder identifier * @property {number} [ssrc] - SSRC this forwarder is using From 2cfb8801b35111ccb147285103d87e06732b7015 Mon Sep 17 00:00:00 2001 From: Samuele Date: Fri, 9 Feb 2024 10:59:32 +0100 Subject: [PATCH 042/114] Add admin_key to createRtpMountpoint (#36) --- src/plugins/streaming-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index 5f6145e..fed0417 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -530,6 +530,7 @@ class StreamingHandle extends Handle { * @param {string} [params.description] - A description for the mp * @param {string} [params.secret] - The secret that'll be needed to edit this mountpoint * @param {string} [params.pin] - The pin that'll be needed to connect to the new mountpoint + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @param {boolean} [params.permanent=false] - True if Janus must persist the mp on a config file * @param {boolean} [params.is_private=false] - Flag the mp as private * @param {boolean} [params.e2ee=false] - True to set a a mp as end to end encrypted @@ -558,7 +559,7 @@ class StreamingHandle extends Handle { * @param {object} [params.metadata] - An opaque metadata to add to the mp * @returns {Promise} */ - async createRtpMountpoint({ id = 0, name, description, secret, pin, permanent = false, is_private = false, e2ee = false, audio, video, data, threads, metadata }) { + async createRtpMountpoint({ id = 0, name, description, secret, pin, admin_key, permanent = false, is_private = false, e2ee = false, audio, video, data, threads, metadata }) { const body = { request: REQUEST_CREATE, type: 'rtp', @@ -575,6 +576,7 @@ class StreamingHandle extends Handle { if (typeof description === 'string') body.description = description; if (typeof secret === 'string') body.secret = secret; if (typeof pin === 'string') body.pin = pin; + if (typeof admin_key === 'string') body.admin_key = admin_key; if (typeof audio === 'object' && audio) { body.audio = true; body.audioport = (typeof audio.port === 'number') ? audio.port : 0; From 28d019cd263602cfd35e8c118f8af88302c3a47b Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 9 Feb 2024 11:07:34 +0100 Subject: [PATCH 043/114] streaming: add "admin_key" parameter to list API --- src/plugins/streaming-plugin.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index fed0417..d6282ad 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -376,12 +376,15 @@ class StreamingHandle extends Handle { /** * List all the available mountpoints. * + * @param {object} params + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ - async list() { + async list({ admin_key } = {}) { const body = { request: REQUEST_LIST, }; + if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; From 1090ff422bbf2896a0912b0816b02fb23af2688c Mon Sep 17 00:00:00 2001 From: Samuele Date: Fri, 9 Feb 2024 12:24:40 +0100 Subject: [PATCH 044/114] videoroom: add "admin_key" parameter to list, create and stop_rtp_forward APIs (#37) --- src/plugins/videoroom-plugin.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 693b3a8..010b0f0 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -1071,12 +1071,15 @@ class VideoRoomHandle extends Handle { /** * List all the available rooms. * + * @param {object} params + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ - async list() { + async list({ admin_key } = {}) { const body = { request: REQUEST_LIST_ROOMS, }; + if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; @@ -1097,6 +1100,7 @@ class VideoRoomHandle extends Handle { * @param {boolean} [params.is_private] - Make the room private (hidden from listing) * @param {string} [params.secret] - The secret that will be used to modify the room * @param {string} [params.pin] - The pin needed to access the room + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @param {number} [params.bitrate] - The bitrate cap that will be used for publishers * @param {boolean} [params.bitrate_cap] - Make the bitrate cap an insormountable limit * @param {number} [params.fir_freq] - The PLI interval in seconds @@ -1113,7 +1117,7 @@ class VideoRoomHandle extends Handle { * @param {string} [params.h264_profile] - H264 specific profile to prefer * @returns {Promise} */ - async create({ room, description, max_publishers, permanent, is_private, secret, pin, bitrate, + async create({ room, description, max_publishers, permanent, is_private, secret, pin, admin_key, bitrate, bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile }) { const body = { @@ -1126,6 +1130,7 @@ class VideoRoomHandle extends Handle { if (typeof is_private === 'boolean') body.is_private = is_private; if (typeof secret === 'string') body.secret = secret; if (typeof pin === 'string') body.pin = pin; + if (typeof admin_key === 'string') body.admin_key = admin_key; if (typeof bitrate === 'number') body.bitrate = bitrate; if (typeof bitrate_cap === 'boolean') body.bitrate_cap = bitrate_cap; if (typeof fir_freq === 'number') body.fir_freq = fir_freq; @@ -1260,9 +1265,10 @@ class VideoRoomHandle extends Handle { * @param {number|string} params.feed - The feed identifier for the forwarder to stop (must be published) * @param {number|string} params.stream - The forwarder identifier as returned by the start forward API * @param {string} [params.secret] - The secret needed for managing the room + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ - async stopForward({ room, feed, stream, secret }) { + async stopForward({ room, feed, stream, secret, admin_key }) { const body = { request: REQUEST_RTP_FWD_STOP, room, @@ -1270,6 +1276,7 @@ class VideoRoomHandle extends Handle { stream_id: stream, }; if (typeof secret === 'string') body.secret = secret; + if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; From 7b976c92cbb5ab9bcba7ab32c34f8ca8d0823def Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 28 Feb 2024 12:29:48 +0100 Subject: [PATCH 045/114] Fix browser bundling example --- examples/browser/bundle.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/browser/bundle.sh b/examples/browser/bundle.sh index b7b3b10..c14a252 100755 --- a/examples/browser/bundle.sh +++ b/examples/browser/bundle.sh @@ -23,6 +23,7 @@ export default { EOF cat < config.js +import replace from '@rollup/plugin-replace'; import nodePolyfills from 'rollup-plugin-polyfill-node'; import nodeResolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; @@ -35,6 +36,11 @@ export default { name: '$EXPORTED_OBJECT' }, plugins: [ + replace({ + preventAssignment: false, + "import UnixTransport from './transport-unix.js'" : "function UnixTransport() { this.open = _ => Logger.error('unix-dgram unsupported on browsers')}", + delimiters: ['', ''] + }), nodePolyfills(), nodeResolve({ browser: true }), commonjs() @@ -42,7 +48,7 @@ export default { }; EOF -npm install --no-save rollup-plugin-polyfill-node @rollup/plugin-node-resolve @rollup/plugin-commonjs +npm install --no-save @rollup/plugin-replace rollup-plugin-polyfill-node @rollup/plugin-node-resolve @rollup/plugin-commonjs rollup --config config.js cp ./app/*.* $DEPLOY_DIR From 34c483145c4c6f30a1acf924dab87ed6378beded Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 29 Feb 2024 12:34:56 +0100 Subject: [PATCH 046/114] gitignore: update --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ad7cb48..eeff83f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ bundle.js *.log *.pem *.crt +*.sh !.eslintrc.json !package.json From 0171687028facf16f5d1a956709451f72eaa565f Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 29 Feb 2024 12:42:49 +0100 Subject: [PATCH 047/114] version: bump to v1.6.11 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6da4f98..da3d317 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.6.10", + "version": "1.6.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.6.9", + "version": "1.6.11", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index 9aa4051..80ce65a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.6.10", + "version": "1.6.11", "type": "module", "keywords": [ "janus", From 084aadc7e8b48e5b547d0d6da39106346882b020 Mon Sep 17 00:00:00 2001 From: Guilherme Marcello <58813280+guilherme-marcello@users.noreply.github.com> Date: Sat, 2 Mar 2024 13:59:42 +0000 Subject: [PATCH 048/114] Add WebRTC Data Channel Support to streaming-client.js (#38) --- examples/streaming/html/streaming-client.js | 39 ++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/examples/streaming/html/streaming-client.js b/examples/streaming/html/streaming-client.js index 4dc1f48..01cf4df 100644 --- a/examples/streaming/html/streaming-client.js +++ b/examples/streaming/html/streaming-client.js @@ -10,6 +10,8 @@ const remoteVideo = document.getElementById('remoteVideo'); const myStream = parseInt(getURLParameter('stream')) || 1; const myPin = getURLParameter('pin') || null; +let decoder; + const button = document.getElementById('button'); button.onclick = () => { if (socket.connected) @@ -273,6 +275,31 @@ socket.on('created', ({ data }) => console.log('mountpoint created', data)); socket.on('destroyed', ({ data }) => console.log('mountpoint destroyed', data)); +function _setupDataChannelCallbacks(channel, isLocal) { + const labelPrefix = isLocal ? 'Local' : 'Remote'; + + channel.onopen = (event) => { + console.log(`${labelPrefix} Datachannel ${channel.id} (${channel.label}) open`); + }; + + channel.onmessage = (event) => { + decoder = decoder || new TextDecoder(); // initialize the decoder + let decodedData = event.data; + if (event.data?.byteLength) { // is ArrayBuffer + decodedData = decoder.decode(event.data); + } + console.log(`${labelPrefix} Datachannel ${channel.id} (${channel.label}) received`, decodedData); + }; + + channel.onclose = () => { + console.log(`${labelPrefix} Datachannel ${channel.id} (${channel.label}) closed`); + }; + + channel.onerror = (error) => { + console.error(`${labelPrefix} Datachannel ${channel.id} (${channel.label}) error:`, error); + }; +} + async function doAnswer(offer) { if (!streamingPeerConnection) { const pc = new RTCPeerConnection({ @@ -282,6 +309,16 @@ async function doAnswer(offer) { //'sdpSemantics': 'unified-plan', }); + // inspect the offer.sdp for m=application lines before creating the DataChannel + if (/m=application [1-9]\d*/.test(offer.sdp)) { + const localChannel = pc.createDataChannel("JanusDataChannel"); + _setupDataChannelCallbacks(localChannel, true); + + pc.ondatachannel = (event) => { + const remoteChannel = event.channel; + _setupDataChannelCallbacks(remoteChannel, false); + }; + } pc.onnegotiationneeded = event => console.log('pc.onnegotiationneeded', event); pc.onicecandidate = event => trickle({ candidate: event.candidate }); pc.oniceconnectionstatechange = () => { @@ -343,4 +380,4 @@ function closePC(pc = streamingPeerConnection) { pc.ontrack = null; pc.close(); if (pc === streamingPeerConnection) streamingPeerConnection = null; -} \ No newline at end of file +} From 4b7fb382acc96c25204c4d072c5ec06d6391d39f Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 4 Mar 2024 12:57:02 +0100 Subject: [PATCH 049/114] examples: lint streaming js client --- examples/streaming/html/streaming-client.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/streaming/html/streaming-client.js b/examples/streaming/html/streaming-client.js index 01cf4df..a0ab12b 100644 --- a/examples/streaming/html/streaming-client.js +++ b/examples/streaming/html/streaming-client.js @@ -276,10 +276,10 @@ socket.on('created', ({ data }) => console.log('mountpoint created', data)); socket.on('destroyed', ({ data }) => console.log('mountpoint destroyed', data)); function _setupDataChannelCallbacks(channel, isLocal) { - const labelPrefix = isLocal ? 'Local' : 'Remote'; + const dcLogPrefix = `${isLocal ? 'Local' : 'Remote'} Datachannel ${channel.id} (${channel.label})`; - channel.onopen = (event) => { - console.log(`${labelPrefix} Datachannel ${channel.id} (${channel.label}) open`); + channel.onopen = (_event) => { + console.log(`${dcLogPrefix} open`); }; channel.onmessage = (event) => { @@ -288,15 +288,15 @@ function _setupDataChannelCallbacks(channel, isLocal) { if (event.data?.byteLength) { // is ArrayBuffer decodedData = decoder.decode(event.data); } - console.log(`${labelPrefix} Datachannel ${channel.id} (${channel.label}) received`, decodedData); + console.log(`${dcLogPrefix} received`, decodedData); }; channel.onclose = () => { - console.log(`${labelPrefix} Datachannel ${channel.id} (${channel.label}) closed`); + console.log(`${dcLogPrefix} closed`); }; channel.onerror = (error) => { - console.error(`${labelPrefix} Datachannel ${channel.id} (${channel.label}) error:`, error); + console.error(`${dcLogPrefix} error`, error); }; } @@ -311,9 +311,9 @@ async function doAnswer(offer) { // inspect the offer.sdp for m=application lines before creating the DataChannel if (/m=application [1-9]\d*/.test(offer.sdp)) { - const localChannel = pc.createDataChannel("JanusDataChannel"); + const localChannel = pc.createDataChannel('JanusDataChannel'); _setupDataChannelCallbacks(localChannel, true); - + pc.ondatachannel = (event) => { const remoteChannel = event.channel; _setupDataChannelCallbacks(remoteChannel, false); From 214f732c6f2f0fbf7d3f9f186267ee160940efa8 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 6 Mar 2024 11:18:48 +0100 Subject: [PATCH 050/114] Test --- src/test | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/test diff --git a/src/test b/src/test new file mode 100644 index 0000000..e69de29 From 8131fee67bb22dca885d0e8126bfb0b1492eea7e Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 11 Mar 2024 15:35:06 +0100 Subject: [PATCH 051/114] videoroom: add vp9 profile to create --- src/plugins/videoroom-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 010b0f0..805bf23 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -1115,11 +1115,12 @@ class VideoRoomHandle extends Handle { * @param {string} [params.rec_dir] - Folder where recordings should be stored * @param {boolean} [params.videoorient] - Whether the video-orientation RTP extension must be negotiated * @param {string} [params.h264_profile] - H264 specific profile to prefer + * @param {string} [params.vp9_profile] - VP9 specific profile to prefer * @returns {Promise} */ async create({ room, description, max_publishers, permanent, is_private, secret, pin, admin_key, bitrate, bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, - require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile }) { + require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile, vp9_profile }) { const body = { request: REQUEST_CREATE, }; @@ -1145,6 +1146,7 @@ class VideoRoomHandle extends Handle { if (typeof rec_dir === 'string') body.rec_dir = rec_dir; if (typeof videoorient === 'boolean') body.videoorient_ext = videoorient; if (typeof h264_profile === 'string') body.h264_profile = h264_profile; + if (typeof vp9_profile === 'string') body.vp9_profile = vp9_profile; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; From 14ce8af700293cf7bc9a458d73e2e4d3dad4fe89 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 28 Mar 2024 18:05:20 +0100 Subject: [PATCH 052/114] videoroom example: update deps, await detach, do not detach when unpublished, small wep app refactoring --- examples/videoroom/html/videoroom-client.js | 23 ++-- examples/videoroom/package-lock.json | 141 ++++++++++++-------- examples/videoroom/src/index.js | 22 +-- 3 files changed, 115 insertions(+), 71 deletions(-) diff --git a/examples/videoroom/html/videoroom-client.js b/examples/videoroom/html/videoroom-client.js index 7e9a7e3..5987b94 100644 --- a/examples/videoroom/html/videoroom-client.js +++ b/examples/videoroom/html/videoroom-client.js @@ -10,6 +10,7 @@ let pendingOfferMap = new Map(); const myRoom = getURLParameter('room') ? parseInt(getURLParameter('room')) : (getURLParameter('room_str') || 1234); const randName = ('John_Doe_' + Math.floor(10000 * Math.random())); const myName = getURLParameter('name') || randName; +let myFeed; const button = document.getElementById('button'); button.onclick = () => { @@ -48,6 +49,11 @@ const socket = io({ reconnection: false, }); +async function _publish(feed = myFeed, display) { + const offer = await doOffer(feed, display); + configure({ feed: feed, jsep: offer }); +} + function join({ room = myRoom, display = myName, token = null } = {}) { const joinData = { room, @@ -115,7 +121,7 @@ function configure({ feed, jsep, restart, substream, temporal }) { if (jsep) pendingOfferMap.set(configId, { feed }); } -function _unpublish({ feed }) { +function _unpublish({ feed = myFeed } = {}) { const unpublishData = { feed, }; @@ -126,7 +132,7 @@ function _unpublish({ feed }) { }); } -function _leave({ feed }) { +function _leave({ feed = myFeed } = {}) { const leaveData = { feed, }; @@ -260,7 +266,7 @@ function _allow({ room = myRoom, action, token, secret = 'adminpwd' }) { }); } -function _startForward({ feed, room = myRoom, host = 'localhost', audio_port, video_port, data_port = null, secret = 'adminpwd' }) { +function _startForward({ feed = myFeed, room = myRoom, host = 'localhost', audio_port, video_port, data_port = null, secret = 'adminpwd' }) { socket.emit('rtp-fwd-start', { data: { room, @@ -275,7 +281,7 @@ function _startForward({ feed, room = myRoom, host = 'localhost', audio_port, vi }); } -function _stopForward({ stream, feed, room = myRoom, secret = 'adminpwd' }) { +function _stopForward({ stream, feed = myFeed, room = myRoom, secret = 'adminpwd' }) { socket.emit('rtp-fwd-stop', { data: { room, @@ -287,7 +293,7 @@ function _stopForward({ stream, feed, room = myRoom, secret = 'adminpwd' }) { }); } -function _listForward({ room = myRoom, secret = 'adminpwd' }) { +function _listForward({ room = myRoom, secret = 'adminpwd' } = {}) { socket.emit('rtp-fwd-list', { data: { room, secret }, _id: getId(), @@ -327,8 +333,7 @@ socket.on('joined', async ({ data }) => { setLocalVideoElement(null, null, null, data.room); try { - const offer = await doOffer(data.feed, data.display, false); - configure({ feed: data.feed, jsep: offer }); + await _publish(data.feed, data.display); subscribeTo(data.publishers, data.room); } catch (e) { console.log('error while doing offer', e); @@ -454,8 +459,7 @@ socket.on('rtp-fwd-list', ({ data }) => { }); async function _restartPublisher(feed) { - const offer = await doOffer(feed, null); - configure({ feed, jsep: offer }); + return await _publish(feed, null); } async function _restartSubscriber(feed) { @@ -501,6 +505,7 @@ async function doOffer(feed, display) { console.log('Performing ICE restart'); pcMap.get(feed).restartIce(); } + myFeed = feed; try { const pc = pcMap.get(feed); diff --git a/examples/videoroom/package-lock.json b/examples/videoroom/package-lock.json index 7553a88..c9a6154 100644 --- a/examples/videoroom/package-lock.json +++ b/examples/videoroom/package-lock.json @@ -63,12 +63,12 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -76,7 +76,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -94,13 +94,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -126,9 +131,9 @@ } }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -159,16 +164,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/depd": { @@ -258,6 +266,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -272,16 +299,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -354,15 +381,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -379,20 +410,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -412,9 +443,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -600,9 +631,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -680,14 +711,16 @@ } }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -699,13 +732,17 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" diff --git a/examples/videoroom/src/index.js b/examples/videoroom/src/index.js index adda381..8b93e49 100644 --- a/examples/videoroom/src/index.js +++ b/examples/videoroom/src/index.js @@ -171,17 +171,19 @@ function initFrontEnd() { replyEvent(socket, 'feed-joined', evtdata); }); - pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_UNPUBLISHED, evtdata => { + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_UNPUBLISHED, async evtdata => { const handle = clientHandles.getHandleByFeed(evtdata.feed); - clientHandles.removeHandleByFeed(evtdata.feed); - if (handle) handle.detach().catch(() => { }); + if (handle.feed !== pubHandle.feed) { + clientHandles.removeHandleByFeed(evtdata.feed); + await handle.detach().catch(() => { }); + } replyEvent(socket, 'unpublished', evtdata); }); - pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_LEAVING, evtdata => { + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_LEAVING, async evtdata => { const handle = clientHandles.getHandleByFeed(evtdata.feed); clientHandles.removeHandleByFeed(evtdata.feed); - if (handle) handle.detach().catch(() => { }); + if (handle) await handle.detach().catch(() => { }); replyEvent(socket, 'leaving', evtdata); }); @@ -193,10 +195,10 @@ function initFrontEnd() { replyEvent(socket, 'talking', evtdata); }); - pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_KICKED, evtdata => { + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_KICKED, async evtdata => { const handle = clientHandles.getHandleByFeed(evtdata.feed); clientHandles.removeHandleByFeed(evtdata.feed); - if (handle) handle.detach().catch(() => { }); + if (handle) await handle.detach().catch(() => { }); replyEvent(socket, 'kicked', evtdata); }); @@ -217,7 +219,7 @@ function initFrontEnd() { Logger.info(`${LOG_NS} ${remote} joined sent`); } catch ({ message }) { - if (pubHandle) pubHandle.detach().catch(() => { }); + if (pubHandle) await pubHandle.detach().catch(() => { }); replyError(socket, message, joindata, _id); } }); @@ -255,7 +257,7 @@ function initFrontEnd() { replyEvent(socket, 'subscribed', response, _id); Logger.info(`${LOG_NS} ${remote} subscribed sent`); } catch ({ message }) { - if (subHandle) subHandle.detach().catch(() => { }); + if (subHandle) await subHandle.detach().catch(() => { }); replyError(socket, message, joindata, _id); } }); @@ -320,7 +322,7 @@ function initFrontEnd() { const response = await handle.leave(); replyEvent(socket, 'leaving', response, _id); Logger.info(`${LOG_NS} ${remote} leaving sent`); - handle.detach().catch(() => { }); + await handle.detach().catch(() => { }); } catch ({ message }) { replyError(socket, message, leavedata, _id); } From 7c6d0f3e603ed57a863c8eddd7aeac1c6891b30e Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 10 Apr 2024 17:50:38 +0200 Subject: [PATCH 053/114] audiobridge: add "admin_key" to create and rtp forward APIs --- src/plugins/audiobridge-plugin.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index f67b58b..362a33f 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -643,6 +643,7 @@ class AudioBridgeHandle extends Handle { * @param {boolean} [params.is_private] - Set room as private (hidden in list) * @param {string} [params.secret] - The secret to be used when managing the room * @param {string} [params.pin] - The ping needed for joining the room + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @param {boolean} [params.record] - True to record the mixed audio * @param {string} [params.filename] - The recording filename * @param {string} [params.rec_dir] - The optional recording folder @@ -655,7 +656,7 @@ class AudioBridgeHandle extends Handle { * @param {string[]} [params.groups] - The available groups in the room * @returns {Promise} */ - async create({ room, description, permanent, sampling_rate, bitrate, is_private, secret, pin, record, filename, rec_dir, + async create({ room, description, permanent, sampling_rate, bitrate, is_private, secret, pin, admin_key, record, filename, rec_dir, talking_events, talking_level_threshold, talking_packets_threshold, expected_loss, prebuffer, allow_rtp, groups }) { const body = { request: REQUEST_CREATE, @@ -668,6 +669,7 @@ class AudioBridgeHandle extends Handle { if (typeof is_private === 'boolean') body.is_private = is_private; if (typeof secret === 'string') body.secret = secret; if (typeof pin === 'string') body.pin = pin; + if (typeof admin_key === 'string') body.admin_key = admin_key; if (typeof record === 'boolean') body.record = record; if (typeof filename === 'string') body.record_file = filename; if (typeof rec_dir === 'string') body.record_dir = rec_dir; @@ -784,9 +786,10 @@ class AudioBridgeHandle extends Handle { * @param {string} [params.codec] - The codec to use in the forwarder * @param {string} [params.group] - The group to forward * @param {string} [params.secret] - The optional secret needed to manage the room + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ - async startForward({ room, always, host, host_family, audio_port, ssrc, ptype, codec, group, secret }) { + async startForward({ room, always, host, host_family, audio_port, ssrc, ptype, codec, group, secret, admin_key }) { const body = { request: REQUEST_RTP_FWD_START, room, @@ -800,6 +803,7 @@ class AudioBridgeHandle extends Handle { if (typeof codec === 'string') body.codec = codec; if (typeof group === 'string') body.group = group; if (typeof secret === 'string') body.secret = secret; + if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; @@ -816,15 +820,17 @@ class AudioBridgeHandle extends Handle { * @param {number|string} params.room - The involved room * @param {number} params.stream - The forwarder identifier to stop * @param {string} [params.secret] - The optional secret needed to manage the room + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ - async stopForward({ room, stream, secret }) { + async stopForward({ room, stream, secret, admin_key }) { const body = { request: REQUEST_RTP_FWD_STOP, room, stream_id: stream, }; if (typeof secret === 'string') body.secret = secret; + if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; @@ -840,14 +846,16 @@ class AudioBridgeHandle extends Handle { * @param {object} params * @param {number|string} params.room - The involved room * @param {string} [params.secret] - The optional secret needed to manage the room + * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ - async listForward({ room, secret }) { + async listForward({ room, secret, admin_key }) { const body = { request: REQUEST_RTP_FWD_LIST, room, }; if (typeof secret === 'string') body.secret = secret; + if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; From c7eed0f8f77d90b79db9a58b392882f76e8e1f40 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 15 Apr 2024 11:28:58 +0200 Subject: [PATCH 054/114] Remove an empty file --- src/test | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/test diff --git a/src/test b/src/test deleted file mode 100644 index e69de29..0000000 From 7f647bf65f6a6da622ac0392b6d72eb368b92fe5 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 6 May 2024 17:07:13 +0200 Subject: [PATCH 055/114] audiobridge: add denoise parameter to create --- src/plugins/audiobridge-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index 362a33f..ef5c4f9 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -654,10 +654,11 @@ class AudioBridgeHandle extends Handle { * @param {number} [params.prebuffer] - The prebuffer to use for every participant * @param {boolean} [params.allow_rtp] - Allow plain RTP participants * @param {string[]} [params.groups] - The available groups in the room + * @param {boolean} [params.denoise] - Enable denoising with rnnoise for all participants * @returns {Promise} */ async create({ room, description, permanent, sampling_rate, bitrate, is_private, secret, pin, admin_key, record, filename, rec_dir, - talking_events, talking_level_threshold, talking_packets_threshold, expected_loss, prebuffer, allow_rtp, groups }) { + talking_events, talking_level_threshold, talking_packets_threshold, expected_loss, prebuffer, allow_rtp, groups, denoise }) { const body = { request: REQUEST_CREATE, room, @@ -680,6 +681,7 @@ class AudioBridgeHandle extends Handle { if (typeof prebuffer === 'number') body.default_prebuffering = prebuffer; if (typeof allow_rtp === 'boolean') body.allow_rtp_participants = allow_rtp; if (Array.isArray(groups)) body.groups = groups; + if (typeof denoise === 'boolean') body.denoise = denoise; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; From b36e0f1171636947c4df1a6d95e0b5bb61371da2 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 13 Jun 2024 13:34:09 +0200 Subject: [PATCH 056/114] Migrate to eslint v9 with flat configs and update all dependencies --- .eslintrc.json | 40 -- eslint.config.js | 53 +++ examples/audiobridge/html/.eslintrc.json | 5 - .../audiobridge/html/audiobridge-client.js | 1 - examples/audiobridge/package-lock.json | 223 +++++++---- examples/echotest/html/.eslintrc.json | 5 - examples/echotest/package-lock.json | 223 +++++++---- examples/streaming/html/.eslintrc.json | 5 - examples/streaming/html/streaming-client.js | 2 - examples/streaming/package-lock.json | 223 +++++++---- examples/videoroom/html/.eslintrc.json | 5 - examples/videoroom/html/videoroom-client.js | 1 - examples/videoroom/package-lock.json | 82 ++-- package-lock.json | 369 +++++++----------- package.json | 12 +- src/transport-unix.js | 2 +- src/utils/utils.js | 2 +- 17 files changed, 680 insertions(+), 573 deletions(-) delete mode 100644 .eslintrc.json create mode 100644 eslint.config.js delete mode 100644 examples/audiobridge/html/.eslintrc.json delete mode 100644 examples/echotest/html/.eslintrc.json delete mode 100644 examples/streaming/html/.eslintrc.json delete mode 100644 examples/videoroom/html/.eslintrc.json diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 9e37304..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "env": { - "node": true, - "browser": false, - "es2021": true - }, - "extends": "eslint:recommended", - "parserOptions": { - "sourceType": "module", - "ecmaVersion": "latest" - }, - "rules": { - "no-unused-vars": [ - "warn", - { - "vars": "all", - "args": "all", - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_" - } - ], - "indent": [ - "warn", - 2, - { - "SwitchCase": 1 - } - ], - "quotes": [ - "warn", - "single" - ], - "semi": [ - "warn", - "always" - ], - "no-empty": "off", - "multiline-comment-style": 1 - } -} \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..843f7cc --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,53 @@ +import globals from 'globals'; +import js from '@eslint/js'; + +export default [ + { + files: [ + '.src/**/*.js', + '.examples/**/*.js' + ], + ignores: [ + '.examples/browser/*' + ], + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + globals: { + ...globals.browser, + ...globals.node + } + }, + rules: { + ...js.configs.recommended.rules, + 'no-unused-vars': [ + 'warn', + { + 'args': 'all', + 'vars': 'all', + 'caughtErrors': 'all', + 'argsIgnorePattern': '^_', + 'varsIgnorePattern': '^_', + 'caughtErrorsIgnorePattern': '^_' + } + ], + 'indent': [ + 'warn', + 2, + { + 'SwitchCase': 1 + } + ], + 'quotes': [ + 'warn', + 'single' + ], + 'semi': [ + 'warn', + 'always' + ], + 'no-empty': 'off', + 'multiline-comment-style': 1 + } + } +]; \ No newline at end of file diff --git a/examples/audiobridge/html/.eslintrc.json b/examples/audiobridge/html/.eslintrc.json deleted file mode 100644 index 5c3f02e..0000000 --- a/examples/audiobridge/html/.eslintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "env": { - "browser": true - } -} \ No newline at end of file diff --git a/examples/audiobridge/html/audiobridge-client.js b/examples/audiobridge/html/audiobridge-client.js index aed7963..7cefe9a 100644 --- a/examples/audiobridge/html/audiobridge-client.js +++ b/examples/audiobridge/html/audiobridge-client.js @@ -1,4 +1,3 @@ -/* eslint-disable no-sparse-arrays */ /* global io */ 'use strict'; diff --git a/examples/audiobridge/package-lock.json b/examples/audiobridge/package-lock.json index 5884c82..835af6a 100644 --- a/examples/audiobridge/package-lock.json +++ b/examples/audiobridge/package-lock.json @@ -12,9 +12,9 @@ } }, "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@types/cookie": { "version": "0.4.1", @@ -22,17 +22,17 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.16", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", - "integrity": "sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==", + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", "dependencies": { "undici-types": "~5.26.4" } @@ -63,12 +63,12 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -76,7 +76,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -94,13 +94,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -126,9 +131,9 @@ } }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -159,16 +164,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/depd": { @@ -202,9 +210,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", - "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -222,9 +230,9 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", "engines": { "node": ">=10.0.0" } @@ -238,9 +246,9 @@ } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -258,6 +266,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -272,16 +299,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -354,15 +381,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -379,20 +410,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -412,9 +443,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -600,9 +631,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -680,14 +711,16 @@ } }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -699,22 +732,26 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/socket.io": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", - "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -729,13 +766,35 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", "dependencies": { + "debug": "~4.3.4", "ws": "~8.11.0" } }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -749,9 +808,9 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -770,9 +829,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, diff --git a/examples/echotest/html/.eslintrc.json b/examples/echotest/html/.eslintrc.json deleted file mode 100644 index 5c3f02e..0000000 --- a/examples/echotest/html/.eslintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "env": { - "browser": true - } -} \ No newline at end of file diff --git a/examples/echotest/package-lock.json b/examples/echotest/package-lock.json index 68d5b1e..bf94428 100644 --- a/examples/echotest/package-lock.json +++ b/examples/echotest/package-lock.json @@ -12,9 +12,9 @@ } }, "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@types/cookie": { "version": "0.4.1", @@ -22,17 +22,17 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.16", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", - "integrity": "sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==", + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", "dependencies": { "undici-types": "~5.26.4" } @@ -63,12 +63,12 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -76,7 +76,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -94,13 +94,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -126,9 +131,9 @@ } }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -159,16 +164,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/depd": { @@ -202,9 +210,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", - "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -222,9 +230,9 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", "engines": { "node": ">=10.0.0" } @@ -238,9 +246,9 @@ } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -258,6 +266,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -272,16 +299,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -354,15 +381,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -379,20 +410,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -412,9 +443,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -600,9 +631,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -680,14 +711,16 @@ } }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -699,22 +732,26 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/socket.io": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", - "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -729,13 +766,35 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", "dependencies": { + "debug": "~4.3.4", "ws": "~8.11.0" } }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -749,9 +808,9 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -770,9 +829,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, diff --git a/examples/streaming/html/.eslintrc.json b/examples/streaming/html/.eslintrc.json deleted file mode 100644 index 5c3f02e..0000000 --- a/examples/streaming/html/.eslintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "env": { - "browser": true - } -} \ No newline at end of file diff --git a/examples/streaming/html/streaming-client.js b/examples/streaming/html/streaming-client.js index a0ab12b..d32e0de 100644 --- a/examples/streaming/html/streaming-client.js +++ b/examples/streaming/html/streaming-client.js @@ -1,4 +1,3 @@ -/* eslint-disable multiline-comment-style */ /* global io */ 'use strict'; @@ -25,7 +24,6 @@ function getId() { } function getURLParameter(name) { - /* eslint-disable-next-line no-sparse-arrays */ return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ''])[1].replace(/\+/g, '%20')) || null; } diff --git a/examples/streaming/package-lock.json b/examples/streaming/package-lock.json index 6b19b3f..356288b 100644 --- a/examples/streaming/package-lock.json +++ b/examples/streaming/package-lock.json @@ -12,9 +12,9 @@ } }, "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@types/cookie": { "version": "0.4.1", @@ -22,17 +22,17 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.16", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", - "integrity": "sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==", + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", "dependencies": { "undici-types": "~5.26.4" } @@ -63,12 +63,12 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -76,7 +76,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -94,13 +94,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -126,9 +131,9 @@ } }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -159,16 +164,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/depd": { @@ -202,9 +210,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", - "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -222,9 +230,9 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", "engines": { "node": ">=10.0.0" } @@ -238,9 +246,9 @@ } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -258,6 +266,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -272,16 +299,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -354,15 +381,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -379,20 +410,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -412,9 +443,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -600,9 +631,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -680,14 +711,16 @@ } }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -699,22 +732,26 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/socket.io": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", - "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -729,13 +766,35 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", "dependencies": { + "debug": "~4.3.4", "ws": "~8.11.0" } }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -749,9 +808,9 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -770,9 +829,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, diff --git a/examples/videoroom/html/.eslintrc.json b/examples/videoroom/html/.eslintrc.json deleted file mode 100644 index 5c3f02e..0000000 --- a/examples/videoroom/html/.eslintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "env": { - "browser": true - } -} \ No newline at end of file diff --git a/examples/videoroom/html/videoroom-client.js b/examples/videoroom/html/videoroom-client.js index 5987b94..6f22020 100644 --- a/examples/videoroom/html/videoroom-client.js +++ b/examples/videoroom/html/videoroom-client.js @@ -1,4 +1,3 @@ -/* eslint-disable no-sparse-arrays */ /* global io */ 'use strict'; diff --git a/examples/videoroom/package-lock.json b/examples/videoroom/package-lock.json index c9a6154..58d833e 100644 --- a/examples/videoroom/package-lock.json +++ b/examples/videoroom/package-lock.json @@ -12,9 +12,9 @@ } }, "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@types/cookie": { "version": "0.4.1", @@ -22,17 +22,17 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.16", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", - "integrity": "sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==", + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", "dependencies": { "undici-types": "~5.26.4" } @@ -210,9 +210,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", - "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -230,9 +230,9 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", "engines": { "node": ">=10.0.0" } @@ -246,9 +246,9 @@ } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -749,9 +749,9 @@ } }, "node_modules/socket.io": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", - "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -766,13 +766,35 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", "dependencies": { + "debug": "~4.3.4", "ws": "~8.11.0" } }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -786,9 +808,9 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -807,9 +829,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, diff --git a/package-lock.json b/package-lock.json index da3d317..ba7dce3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,19 +14,12 @@ "ws": "^8.0.0" }, "devDependencies": { - "eslint": "^8.25.0" + "@eslint/js": "^9.4.0", + "eslint": "^9.4.0", + "globals": "^15.4.0" }, "engines": { - "node": " >=14.13.1 || >=16.0.0" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": " >=18.18.0" } }, "node_modules/@eslint-community/eslint-utils": { @@ -44,25 +37,51 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.15.1.tgz", + "integrity": "sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -70,33 +89,40 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", + "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -112,11 +138,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -153,12 +186,6 @@ "node": ">= 8" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -314,9 +341,9 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -336,18 +363,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -361,41 +376,37 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.4.0.tgz", + "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/config-array": "^0.15.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.4.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", + "eslint-scope": "^8.0.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.0.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -409,52 +420,52 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", + "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", + "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.11.3", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -521,24 +532,24 @@ "dev": true }, "node_modules/fastq": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", - "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-uri-to-path": { @@ -563,51 +574,24 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -621,26 +605,17 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.4.0.tgz", + "integrity": "sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -651,9 +626,9 @@ } }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -684,22 +659,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -836,9 +795,9 @@ "dev": true }, "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -846,27 +805,18 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -923,15 +873,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -998,21 +939,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -1111,18 +1037,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/unix-dgram": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.6.tgz", @@ -1160,16 +1074,19 @@ "node": ">= 8" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 80ce65a..4234a99 100644 --- a/package.json +++ b/package.json @@ -37,17 +37,19 @@ ], "dependencies": { "isomorphic-ws": "^4.0.1", - "ws": "^8.0.0", - "unix-dgram": "^2.0.4" + "unix-dgram": "^2.0.4", + "ws": "^8.0.0" }, "devDependencies": { - "eslint": "^8.25.0" + "@eslint/js": "^9.4.0", + "eslint": "^9.4.0", + "globals": "^15.4.0" }, "engines": { - "node": " >=14.13.1 || >=16.0.0" + "node": " >=18.18.0" }, "scripts": { "build": "npm install --omit=dev", - "lint": "eslint --ext .js --config .eslintrc.json src" + "lint": "npx eslint" } } diff --git a/src/transport-unix.js b/src/transport-unix.js index 95915f9..e15d3f6 100644 --- a/src/transport-unix.js +++ b/src/transport-unix.js @@ -161,7 +161,7 @@ class TransportUnix { this._socket = socket; - try { unlinkSync(this._local_bind); } catch (error) { } + try { unlinkSync(this._local_bind); } catch (_error) { } socket.bind(this._local_bind); }); } diff --git a/src/utils/utils.js b/src/utils/utils.js index 4d2f1cf..3c7f7e4 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -89,7 +89,7 @@ export const checkUrl = (url_string, admitted) => { /* 'slice(0, -1)' removes the colon at the last position */ const protocol = (new URL(url_string)).protocol.slice(0, -1); return admitted.includes(protocol); - } catch (e) { } + } catch (_error) { } return false; }; From cfbf7a5864cdf58434d9f94b718b747e5c0457b4 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 13 Jun 2024 13:36:14 +0200 Subject: [PATCH 057/114] ci: update node version --- .github/workflows/janode-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/janode-ci.yml b/.github/workflows/janode-ci.yml index 49411b5..b20f831 100644 --- a/.github/workflows/janode-ci.yml +++ b/.github/workflows/janode-ci.yml @@ -14,6 +14,6 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 20 - run: npm ci - run: npm run lint From 5463656ea0bb8dd396d399c5a4417bc93fdcd466 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 13 Jun 2024 13:39:37 +0200 Subject: [PATCH 058/114] Add "--debug" to eslint --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4234a99..aca9685 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,6 @@ }, "scripts": { "build": "npm install --omit=dev", - "lint": "npx eslint" + "lint": "npx eslint --debug" } } From b649cff3892d1d6f72b42b9d699313298c15ed89 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 13 Jun 2024 14:00:46 +0200 Subject: [PATCH 059/114] eslint: update rules --- eslint.config.js | 6 +++--- examples/audiobridge/html/audiobridge-client.js | 1 + examples/streaming/html/streaming-client.js | 2 ++ examples/videoroom/html/videoroom-client.js | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 843f7cc..f4ff71a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -4,11 +4,11 @@ import js from '@eslint/js'; export default [ { files: [ - '.src/**/*.js', - '.examples/**/*.js' + 'src/**/*.js', + 'examples/**/*.js' ], ignores: [ - '.examples/browser/*' + 'examples/browser/**/*' ], languageOptions: { ecmaVersion: 'latest', diff --git a/examples/audiobridge/html/audiobridge-client.js b/examples/audiobridge/html/audiobridge-client.js index 7cefe9a..d54f81f 100644 --- a/examples/audiobridge/html/audiobridge-client.js +++ b/examples/audiobridge/html/audiobridge-client.js @@ -26,6 +26,7 @@ function getId() { } function getURLParameter(name) { + // eslint-disable-next-line no-sparse-arrays return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ''])[1].replace(/\+/g, '%20')) || null; } diff --git a/examples/streaming/html/streaming-client.js b/examples/streaming/html/streaming-client.js index d32e0de..92a169a 100644 --- a/examples/streaming/html/streaming-client.js +++ b/examples/streaming/html/streaming-client.js @@ -1,3 +1,4 @@ +/* eslint-disable multiline-comment-style */ /* global io */ 'use strict'; @@ -24,6 +25,7 @@ function getId() { } function getURLParameter(name) { + // eslint-disable-next-line no-sparse-arrays return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ''])[1].replace(/\+/g, '%20')) || null; } diff --git a/examples/videoroom/html/videoroom-client.js b/examples/videoroom/html/videoroom-client.js index 6f22020..59e1c7d 100644 --- a/examples/videoroom/html/videoroom-client.js +++ b/examples/videoroom/html/videoroom-client.js @@ -24,6 +24,7 @@ function getId() { } function getURLParameter(name) { + // eslint-disable-next-line no-sparse-arrays return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ''])[1].replace(/\+/g, '%20')) || null; } From 19ab36850595b9ed8169e57ccf12fc3e73d2748a Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 13 Jun 2024 14:05:16 +0200 Subject: [PATCH 060/114] videoroom: enhanced multistream support (#40) --- examples/videoroom-ms/html/index.html | 29 + .../videoroom-ms/html/videoroom-ms-client.js | 952 ++++++++++++++++++ examples/videoroom-ms/package-lock.json | 930 +++++++++++++++++ examples/videoroom-ms/package.json | 30 + examples/videoroom-ms/src/config.template.js | 16 + examples/videoroom-ms/src/index.js | 638 ++++++++++++ src/handle.js | 14 +- src/plugins/videoroom-plugin.js | 405 +++++--- 8 files changed, 2883 insertions(+), 131 deletions(-) create mode 100644 examples/videoroom-ms/html/index.html create mode 100644 examples/videoroom-ms/html/videoroom-ms-client.js create mode 100644 examples/videoroom-ms/package-lock.json create mode 100644 examples/videoroom-ms/package.json create mode 100644 examples/videoroom-ms/src/config.template.js create mode 100644 examples/videoroom-ms/src/index.js diff --git a/examples/videoroom-ms/html/index.html b/examples/videoroom-ms/html/index.html new file mode 100644 index 0000000..f0590f9 --- /dev/null +++ b/examples/videoroom-ms/html/index.html @@ -0,0 +1,29 @@ + + + + + VideoRoom Socket.IO Janode + + + + + +

+
+ --- VIDEOROOM () --- +

+ -- LOCALS -- +

+
+

+ -- REMOTES -- +

+
+
+ + + + + + \ No newline at end of file diff --git a/examples/videoroom-ms/html/videoroom-ms-client.js b/examples/videoroom-ms/html/videoroom-ms-client.js new file mode 100644 index 0000000..102eb54 --- /dev/null +++ b/examples/videoroom-ms/html/videoroom-ms-client.js @@ -0,0 +1,952 @@ +/* eslint-disable no-sparse-arrays */ +/* global io */ + +'use strict'; + +const RTCPeerConnection = (window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection).bind(window); + +let pubPc, subPc; +let subscriptions = new Map(); +const pendingOfferMap = new Map(); +const myRoom = getURLParameter('room') ? parseInt(getURLParameter('room')) : (getURLParameter('room_str') || 1234); +const randName = ('John_Doe_' + Math.floor(10000 * Math.random())); +const myName = getURLParameter('name') || randName; +let myFeed; + +const button = document.getElementById('button'); +button.onclick = () => { + if (socket.connected) + socket.disconnect(); + else + socket.connect(); +}; + +function getId() { + return Math.floor(Number.MAX_SAFE_INTEGER * Math.random()); +} + +function getURLParameter(name) { + return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ''])[1].replace(/\+/g, '%20')) || null; +} + +const scheduleConnection = (function () { + let task = null; + const delay = 5000; + + return (function (secs) { + if (task) return; + const timeout = secs * 1000 || delay; + console.log('scheduled joining in ' + timeout + ' ms'); + task = setTimeout(() => { + join(); + task = null; + }, timeout); + }); +})(); + +const socket = io({ + rejectUnauthorized: false, + autoConnect: false, + reconnection: false, +}); + +function join({ room = myRoom, display = myName, token = null } = {}) { + const joinData = { + room, + display, + token, + }; + + socket.emit('join', { + data: joinData, + _id: getId(), + }); +} + +function subscribe({ streams, room = myRoom }) { + const subscribeData = { + room, + streams, + }; + + socket.emit('subscribe', { + data: subscribeData, + _id: getId(), + }); +} + +function subscribeTo(publishers, room = myRoom) { + const newStreams = []; + publishers.forEach(({ feed, streams }) => { + streams.forEach(s => { + if (!hasFeedMidSubscription(feed, s.mid)) { + newStreams.push({ + feed, + mid: s.mid, + }); + } + }); + }); + + if (newStreams.length > 0) { + subscribe({ + streams: newStreams, + room, + }); + } +} + +function trickle({ feed, candidate }) { + const trickleData = candidate ? { candidate } : {}; + if (feed) trickleData.feed = feed; + const trickleEvent = candidate ? 'trickle' : 'trickle-complete'; + + socket.emit(trickleEvent, { + data: trickleData, + _id: getId(), + }); +} + +function configure({ feed, display, jsep, restart, streams }) { + const configureData = {}; + if (feed) configureData.feed = feed; + if (display) configureData.display = display; + if (jsep) configureData.jsep = jsep; + if (streams) configureData.streams = streams; + if (typeof restart === 'boolean') configureData.restart = restart; + + const configId = getId(); + + socket.emit('configure', { + data: configureData, + _id: configId, + }); + + if (jsep) + pendingOfferMap.set(configId, { feed }); +} + +async function _publish({ feed = myFeed, display = myName } = {}) { + try { + const offer = await doOffer(feed, display); + configure({ feed, jsep: offer }); + } catch (e) { + console.log('error while doing offer', e); + } +} + +function _unpublish({ feed = myFeed } = {}) { + const unpublishData = { + feed, + }; + + socket.emit('unpublish', { + data: unpublishData, + _id: getId(), + }); +} + +function _leave({ feed = myFeed } = {}) { + const leaveData = { + feed, + }; + + socket.emit('leave', { + data: leaveData, + _id: getId(), + }); +} + +function _listParticipants({ room = myRoom } = {}) { + const listData = { + room, + }; + + socket.emit('list-participants', { + data: listData, + _id: getId(), + }); +} + +function _kick({ feed, room = myRoom, secret = 'adminpwd' }) { + const kickData = { + room, + feed, + secret, + }; + + socket.emit('kick', { + data: kickData, + _id: getId(), + }); +} + +function start({ jsep = null } = {}) { + const startData = { + jsep, + }; + + socket.emit('start', { + data: startData, + _id: getId(), + }); +} + +function _pause() { + const pauseData = {}; + + socket.emit('pause', { + data: pauseData, + _id: getId(), + }); +} + +function _unsubscribe({ streams, room = myRoom }) { + const unsubscribeData = { + room, + streams, + }; + + socket.emit('unsubscribe', { + data: unsubscribeData, + _id: getId(), + }); +} + +function _switch({ streams }) { + const switchData = { + streams, + }; + + socket.emit('switch', { + data: switchData, + _id: getId(), + }); +} + +function _exists({ room = myRoom } = {}) { + const existsData = { + room, + }; + + socket.emit('exists', { + data: existsData, + _id: getId(), + }); +} + +function _listRooms() { + socket.emit('list-rooms', { + _id: getId(), + }); +} + +function _create({ room, description, max_publishers = 6, audiocodec = 'opus', videocodec = 'vp8', talking_events = false, talking_level_threshold = 25, talking_packets_threshold = 100, permanent = false }) { + socket.emit('create', { + data: { + room, + description, + max_publishers, + audiocodec, + videocodec, + talking_events, + talking_level_threshold, + talking_packets_threshold, + permanent, + }, + _id: getId(), + }); +} + +function _destroy({ room = myRoom, permanent = false, secret = 'adminpwd' }) { + socket.emit('destroy', { + data: { + room, + permanent, + secret, + }, + _id: getId(), + }); +} + +// add remove enable disable token mgmt +function _allow({ room = myRoom, action, token, secret = 'adminpwd' }) { + const allowData = { + room, + action, + secret, + }; + if (action != 'disable' && token) allowData.list = [token]; + + socket.emit('allow', { + data: allowData, + _id: getId(), + }); +} + +function _startForward({ feed = myFeed, host, room = myRoom, streams, secret = 'adminpwd' }) { + socket.emit('rtp-fwd-start', { + data: { + room, + feed, + host, + streams, + secret, + }, + _id: getId(), + }); +} + +function _stopForward({ stream, feed, room = myRoom, secret = 'adminpwd' }) { + socket.emit('rtp-fwd-stop', { + data: { + room, + stream, + feed, + secret, + }, + _id: getId(), + }); +} + +function _listForward({ room = myRoom, secret = 'adminpwd' } = {}) { + socket.emit('rtp-fwd-list', { + data: { room, secret }, + _id: getId(), + }); +} + +socket.on('connect', () => { + console.log('socket connected'); + socket.sendBuffer = []; + scheduleConnection(0.1); +}); + +socket.on('disconnect', () => { + console.log('socket disconnected'); + pendingOfferMap.clear(); + subscriptions.clear(); + removeAllMediaElements(); + closeAllPCs(); +}); + +socket.on('videoroom-error', ({ error, _id }) => { + console.log('videoroom error', error); + if (error === 'backend-failure' || error === 'session-not-available') { + socket.disconnect(); + return; + } + if (pendingOfferMap.has(_id)) { + removeAllLocalMediaElements(); + closePubPc(); + pendingOfferMap.delete(_id); + return; + } +}); + +socket.on('joined', async ({ data }) => { + console.log('joined to room', data); + setLocalMediaElement(null, null, null, data.room); + + try { + await _publish({ feed: data.feed, display: data.display }); + subscribeTo(data.publishers, data.room); + } catch (e) { + console.log('error while publishing', e); + } +}); + +socket.on('subscribed', async ({ data }) => { + console.log('subscribed to feed', data); + /* + * data.streams + * [ + * { + * "type": "audio", + * "active": true, + * "mindex": 0, + * "mid": "0", + * "ready": false, + * "send": true, + * "feed_id": 947374180882471, + * "feed_display": "John_Doe_8186", + * "feed_mid": "0", + * "codec": "opus" + * }, + * { + * "type": "video", + * "active": true, + * "mindex": 1, + * "mid": "1", + * "ready": false, + * "send": true, + * "feed_id": 947374180882471, + * "feed_display": "John_Doe_8186", + * "feed_mid": "1", + * "codec": "vp8" + * } + * ] + */ + updateSubscriptions(data.streams); + + try { + if (data.jsep) { + const answer = await doAnswer(data.jsep); + start({ jsep: answer }); + } + } catch (e) { console.log('error while doing answer', e); } +}); + +socket.on('unsubscribed', async ({ data }) => { + console.log('unsubscribed to feed', data); + /* + * data.streams + * [ + * { + * "type": "audio", + * "active": true, + * "mindex": 0, + * "mid": "0", + * "ready": true, + * "send": true, + * "feed_id": 5431908509285044, + * "feed_display": "John_Doe_2332", + * "feed_mid": "0", + * "codec": "opus" + * }, + * { + * "type": "video", + * "active": false, + * "mindex": 1, + * "mid": "1", + * "ready": false, + * "send": true + * } + * ] + */ + updateSubscriptions(data.streams); + + try { + if (data.jsep) { + const answer = await doAnswer(data.jsep); + start({ jsep: answer }); + } + } catch (e) { console.log('error while doing answer', e); } +}); + +socket.on('updated', async ({ data }) => { + console.log('updated subscription', data); + /* + * data.streams + * [ + * { + * "type": "audio", + * "active": false, + * "mindex": 0, + * "mid": "0", + * "ready": false, + * "send": true + * }, + * { + * "type": "video", + * "active": false, + * "mindex": 1, + * "mid": "1", + * "ready": false, + * "send": true + * } + * ] + */ + updateSubscriptions(data.streams); + + try { + if (data.jsep) { + const answer = await doAnswer(data.jsep); + start({ jsep: answer }); + } + } catch (e) { console.log('error while doing answer', e); } +}); + +socket.on('participants-list', ({ data }) => { + console.log('participants list', data); +}); + +socket.on('talking', ({ data }) => { + console.log('talking notify', data); +}); + +socket.on('kicked', ({ data }) => { + console.log('participant kicked', data); + if (data.feed) { + const streams = subscriptions.values().toArray().map(s => { + const stream = {}; + for (const attr in s) { + stream[attr] = s[attr]; + } + if (stream.feed_id == data.feed) { + stream.active = false; + stream.feed_id = null; + stream.feed_mid = null; + stream.feed_display = null; + } + return stream; + }); + updateSubscriptions(streams); + } +}); + +socket.on('allowed', ({ data }) => { + console.log('token management', data); +}); + +socket.on('configured', async ({ data, _id }) => { + console.log('feed configured', data); + pendingOfferMap.delete(_id); + + const pc = data.feed ? pubPc : subPc; + if (data.jsep) { + try { + await pc.setRemoteDescription(data.jsep); + if (data.jsep.type === 'offer') { + const answer = await doAnswer(data.jsep); + start({ jsep: answer }); + } + console.log('configure remote sdp OK'); + } catch (e) { + console.log('error setting remote sdp', e); + } + } + if (data.display) { + setLocalMediaElement(null, data.feed, data.display); + } +}); + +socket.on('display', ({ data }) => { + console.log('feed changed display name', data); + const streams = subscriptions.values().toArray().map(s => { + if (s.feed_id === data.feed) { + s.feed_display = data.display; + } + return s; + }); + updateSubscriptions(streams); +}); + +socket.on('started', ({ data }) => { + console.log('subscriber feed started', data); +}); + +socket.on('paused', ({ data }) => { + console.log('feed paused', data); +}); + +socket.on('switched', ({ data }) => { + console.log('feed switched', data); + updateSubscriptions(data.streams); +}); + +socket.on('feed-list', ({ data }) => { + console.log('new feeds available!', data); + subscribeTo(data.publishers, data.room); +}); + +socket.on('unpublished', ({ data }) => { + console.log('feed unpublished', data); + if (data.feed) { + if (data.feed === myFeed) { + removeAllLocalMediaElements(); + closePubPc(); + } + } +}); + +socket.on('leaving', ({ data }) => { + console.log('feed leaving', data); + if (data.feed) { + if (data.feed === myFeed) { + removeAllLocalMediaElements(); + closePubPc(); + } + else { + const streams = subscriptions.values().toArray().map(s => { + const stream = {}; + for (const attr in s) { + stream[attr] = s[attr]; + } + if (stream.feed_id == data.feed) { + stream.active = false; + stream.feed_id = null; + stream.feed_mid = null; + stream.feed_display = null; + } + return stream; + }); + updateSubscriptions(streams); + } + } +}); + +socket.on('exists', ({ data }) => { + console.log('room exists', data); +}); + +socket.on('rooms-list', ({ data }) => { + console.log('rooms list', data); +}); + +socket.on('created', ({ data }) => { + console.log('room created', data); +}); + +socket.on('destroyed', ({ data }) => { + console.log('room destroyed', data); + if (data.room === myRoom) { + socket.disconnect(); + } +}); + +socket.on('rtp-fwd-started', ({ data }) => { + console.log('rtp forwarding started', data); +}); + +socket.on('rtp-fwd-stopped', ({ data }) => { + console.log('rtp forwarding stopped', data); +}); + +socket.on('rtp-fwd-list', ({ data }) => { + console.log('rtp forwarders list', data); +}); + +async function _restartPublisher({ feed = myFeed } = {}) { + return _publish({ feed }); +} + +async function _restartSubscriber() { + configure({ restart: true }); +} + +async function doOffer(feed, display) { + if (!pubPc) { + const pc = new RTCPeerConnection({ + 'iceServers': [{ + urls: 'stun:stun.l.google.com:19302' + }], + }); + + pc.onnegotiationneeded = event => console.log('pc.onnegotiationneeded', event); + pc.onicecandidate = event => trickle({ feed, candidate: event.candidate }); + pc.oniceconnectionstatechange = () => { + if (pc.iceConnectionState === 'failed' || pc.iceConnectionState === 'closed') { + removeAllLocalMediaElements(); + closePubPc(); + } + }; + /* This one below should not be fired, cause the PC is used just to send */ + pc.ontrack = event => console.log('pc.ontrack', event); + + pubPc = pc; + + try { + const localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); + localStream.getTracks().forEach(track => { + console.log('adding track', track); + pc.addTrack(track, localStream); + }); + setLocalMediaElement(localStream, feed, display, null); + } catch (e) { + console.log('error while doing offer', e); + removeAllLocalMediaElements(); + closePubPc(); + return; + } + } + else { + console.log('Performing ICE restart'); + pubPc.restartIce(); + } + myFeed = feed; + + try { + const offer = await pubPc.createOffer(); + await pubPc.setLocalDescription(offer); + console.log('set local sdp OK'); + return offer; + } catch (e) { + console.log('error while doing offer', e); + removeAllLocalMediaElements(); + closePubPc(); + return; + } +} + +function hasFeedMidSubscription(feed, mid) { + for (let [_, s] of subscriptions) { + if (s.feed === feed && s.mid === mid) return true; + } + return false; +} + +function updateSubscriptions(streams) { + if (!streams) return; + removeRemoteMediaElements(streams); + const newSubscriptions = new Map(); + streams.forEach(s => { + s.ms = subscriptions.get(s.mid)?.ms; + newSubscriptions.set(s.mid, s); + }); + subscriptions = newSubscriptions; + refreshRemoteMediaElements(); +} + +function removeRemoteMediaElements(new_streams) { + if (!new_streams) return; + const oldSubscriptions = subscriptions; + const oldSubMids = oldSubscriptions.values().toArray().map(s => s.active && s.mid).filter(mid => mid); + const newSubMids = new_streams.values().toArray().map(s => s.active && s.mid).filter(mid => mid); + const deletedSubMids = oldSubMids.filter(mid => !newSubMids.includes(mid)); + deletedSubMids.forEach(mid => removeRemoteMediaElementsBySubMid(mid, false)); +} + +function refreshRemoteMediaElements() { + for (let [sub_mid, s] of subscriptions) { + const { feed_display, type, feed_id, feed_mid, active, ms } = s; + if (active) { + if (type === 'video') + setRemoteVideoElement(ms, sub_mid, [feed_display, feed_id, feed_mid, sub_mid].join('|')); + if (type === 'audio') + setRemoteAudioElement(ms, sub_mid); + } + } +} + +async function doAnswer(offer) { + if (!subPc) { + const pc = new RTCPeerConnection({ + 'iceServers': [{ + urls: 'stun:stun.l.google.com:19302' + }], + }); + + subPc = pc; + + pc.onnegotiationneeded = event => console.log('pc.onnegotiationneeded', event); + pc.onicecandidate = event => trickle({ candidate: event.candidate }); + pc.oniceconnectionstatechange = () => { + if (pc.iceConnectionState === 'failed' || pc.iceConnectionState === 'closed') { + removeAllRemoteMediaElements(); + closeSubPc(); + } + }; + pc.ontrack = event => { + console.log('pc.ontrack', event); + + event.track.onunmute = evt => { + console.log('track.onunmute', evt); + }; + event.track.onmute = evt => { + console.log('track.onmute', evt); + }; + event.track.onended = evt => { + console.log('track.onended', evt); + }; + + /* avoid latching tracks */ + const submid = event.transceiver?.mid || event.receiver.mid; + const remoteStream = event.streams[0].id === 'janus' ? (new MediaStream([event.track])) : event.streams[0]; + if (subscriptions.has(submid)) { + const stream = subscriptions.get(submid); + stream.ms = remoteStream; + refreshRemoteMediaElements(); + } + }; + } + + try { + await subPc.setRemoteDescription(offer); + console.log('set remote sdp OK'); + const answer = await subPc.createAnswer(); + await subPc.setLocalDescription(answer); + console.log('set local sdp OK'); + return answer; + } catch (e) { + console.log('error creating subscriber answer', e); + removeAllRemoteMediaElements(); + closeSubPc(); + throw e; + } +} + +function setLocalMediaElement(localStream, feed, display, room) { + if (room) document.getElementById('videos').getElementsByTagName('span')[0].innerHTML = ' --- VIDEOROOM (' + room + ') --- '; + if (!feed) return; + + const id = `video_${feed}_local`; + let localVideoContainer = document.getElementById(id); + if (!localVideoContainer) { + const nameElem = document.createElement('span'); + nameElem.style.display = 'table'; + + const localVideoStreamElem = document.createElement('video'); + localVideoStreamElem.width = 320; + localVideoStreamElem.height = 240; + localVideoStreamElem.autoplay = true; + localVideoStreamElem.muted = true; + localVideoStreamElem.style.cssText = '-moz-transform: scale(-1, 1); -webkit-transform: scale(-1, 1); -o-transform: scale(-1, 1); transform: scale(-1, 1); filter: FlipH;'; + + localVideoContainer = document.createElement('div'); + localVideoContainer.id = id; + localVideoContainer.appendChild(nameElem); + localVideoContainer.appendChild(localVideoStreamElem); + + document.getElementById('locals').appendChild(localVideoContainer); + } + if (display) { + const nameElem = localVideoContainer.getElementsByTagName('span')[0]; + nameElem.innerHTML = [display, feed].join('|'); + } + if (localStream) { + const localVideoStreamElem = localVideoContainer.getElementsByTagName('video')[0]; + localVideoStreamElem.srcObject = localStream; + } +} + +function setRemoteVideoElement(remoteStream, sub_mid, display) { + if (!sub_mid) return; + + /* Target specific sub_mid/feed/mid */ + const id = `video_remote_${sub_mid}`; + let remoteVideoContainer = document.getElementById(id); + if (!remoteVideoContainer) { + /* Non existing */ + const nameElem = document.createElement('span'); + nameElem.innerHTML = display; + nameElem.style.display = 'table'; + + const remoteVideoStreamElem = document.createElement('video'); + remoteVideoStreamElem.width = 320; + remoteVideoStreamElem.height = 240; + remoteVideoStreamElem.autoplay = true; + remoteVideoStreamElem.style.cssText = '-moz-transform: scale(-1, 1); -webkit-transform: scale(-1, 1); -o-transform: scale(-1, 1); transform: scale(-1, 1); filter: FlipH;'; + + remoteVideoContainer = document.createElement('div'); + remoteVideoContainer.id = id; + remoteVideoContainer.appendChild(nameElem); + remoteVideoContainer.appendChild(remoteVideoStreamElem); + + document.getElementById('remotes').appendChild(remoteVideoContainer); + } + if (display) { + const nameElem = remoteVideoContainer.getElementsByTagName('span')[0]; + nameElem.innerHTML = display; + } + if (remoteStream) { + const remoteVideoStreamElem = remoteVideoContainer.getElementsByTagName('video')[0]; + remoteVideoStreamElem.srcObject = remoteStream; + } +} + +function setRemoteAudioElement(remoteStream, sub_mid) { + if (!sub_mid) return; + + /* Target specific sub_mid/feed/mid */ + const id = `audio_remote_${sub_mid}`; + let remoteAudioContainer = document.getElementById(id); + if (!remoteAudioContainer) { + const remoteAudioStreamElem = document.createElement('audio'); + remoteAudioStreamElem.autoplay = true; + + remoteAudioContainer = document.createElement('div'); + remoteAudioContainer.id = id; + remoteAudioContainer.appendChild(remoteAudioStreamElem); + + document.getElementById('remotes').appendChild(remoteAudioContainer); + } + if (remoteStream) { + const remoteAudioStreamElem = remoteAudioContainer.getElementsByTagName('audio')[0]; + remoteAudioStreamElem.srcObject = remoteStream; + } +} + +function removeMediaElement(container, stopTracks = true) { + let streamElem = null; + if (container.getElementsByTagName('video').length > 0) + streamElem = container.getElementsByTagName('video')[0]; + if (container.getElementsByTagName('audio').length > 0) + streamElem = container.getElementsByTagName('audio')[0]; + if (streamElem && streamElem.srcObject && stopTracks) { + streamElem.srcObject.getTracks().forEach(track => track.stop()); + streamElem.srcObject = null; + } + container.remove(); +} + +function removeRemoteMediaElementsBySubMid(sub_mid, stopTracks) { + const idEndsWith = `_remote_${sub_mid}`; + const containers = document.querySelectorAll(`[id$=${idEndsWith}]`); + containers.forEach(container => removeMediaElement(container, stopTracks)); +} + +function removeAllLocalMediaElements() { + const locals = document.getElementById('locals'); + const localMediaContainers = locals.getElementsByTagName('div'); + for (let i = 0; localMediaContainers && i < localMediaContainers.length; i++) + removeMediaElement(localMediaContainers[i]); + while (locals.firstChild) + locals.removeChild(locals.firstChild); +} + +function removeAllRemoteMediaElements() { + var remotes = document.getElementById('remotes'); + const remoteMediaContainers = remotes.getElementsByTagName('div'); + for (let i = 0; remoteMediaContainers && i < remoteMediaContainers.length; i++) + removeMediaElement(remoteMediaContainers[i]); + while (remotes.firstChild) + remotes.removeChild(remotes.firstChild); +} + +function removeAllMediaElements() { + removeAllLocalMediaElements(); + removeAllRemoteMediaElements(); + document.getElementById('videos').getElementsByTagName('span')[0].innerHTML = ' --- VIDEOROOM () --- '; +} + +function closePubPc() { + if (pubPc) { + console.log('closing pc for publisher'); + _closePC(pubPc); + pubPc = null; + } +} + +function closeSubPc() { + if (subPc) { + console.log('closing pc for subscriber'); + _closePC(subPc); + subPc = null; + } +} + +function _closePC(pc) { + if (!pc) return; + pc.getSenders().forEach(sender => { + if (sender.track) + sender.track.stop(); + }); + pc.getReceivers().forEach(receiver => { + if (receiver.track) + receiver.track.stop(); + }); + pc.onnegotiationneeded = null; + pc.onicecandidate = null; + pc.oniceconnectionstatechange = null; + pc.ontrack = null; + try { + pc.close(); + } catch (_e) { } +} + +function closeAllPCs() { + console.log('closing all pcs'); + closePubPc(); + closeSubPc(); +} diff --git a/examples/videoroom-ms/package-lock.json b/examples/videoroom-ms/package-lock.json new file mode 100644 index 0000000..e42c5ef --- /dev/null +++ b/examples/videoroom-ms/package-lock.json @@ -0,0 +1,930 @@ +{ + "name": "janode-videoroom-ms", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "janode-videoroom-ms", + "license": "ISC", + "dependencies": { + "express": "^4.13.4", + "socket.io": "^4.2.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "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" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/socket.io": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "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" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/examples/videoroom-ms/package.json b/examples/videoroom-ms/package.json new file mode 100644 index 0000000..2e43b92 --- /dev/null +++ b/examples/videoroom-ms/package.json @@ -0,0 +1,30 @@ +{ + "name": "janode-videoroom-ms", + "description": "Janode videoroom multistream app", + "type": "module", + "keywords": [ + "janus", + "webrtc", + "meetecho" + ], + "author": { + "name": "Alessandro Toppi", + "email": "atoppi@meetecho.com" + }, + "repository": { + "type": "git", + "url": "https://github.com/meetecho/janode.git" + }, + "license": "ISC", + "private": true, + "main": "src/index.js", + "dependencies": { + "express": "^4.13.4", + "socket.io": "^4.2.0" + }, + "scripts": { + "build": "npm install --omit=dev", + "build-config": "node -e \"var fs = require('fs');fs.createReadStream('src/config.template.js').pipe(fs.createWriteStream('src/config.js'));\"", + "start": "node src/index.js" + } +} \ No newline at end of file diff --git a/examples/videoroom-ms/src/config.template.js b/examples/videoroom-ms/src/config.template.js new file mode 100644 index 0000000..a82aafe --- /dev/null +++ b/examples/videoroom-ms/src/config.template.js @@ -0,0 +1,16 @@ +export default { + janode: { + address: [{ + url: 'ws://127.0.0.1:8188/', + apisecret: 'secret' + }], + // seconds between retries after a connection setup error + retry_time_secs: 10 + }, + web: { + port: 4443, + bind: '0.0.0.0', + key: '/path/to/key.pem', + cert: '/path/to/cert.pem' + } +}; \ No newline at end of file diff --git a/examples/videoroom-ms/src/index.js b/examples/videoroom-ms/src/index.js new file mode 100644 index 0000000..effa1ee --- /dev/null +++ b/examples/videoroom-ms/src/index.js @@ -0,0 +1,638 @@ +'use strict'; + +import { readFileSync } from 'fs'; +import Janode from '../../../src/janode.js'; +import config from './config.js'; +const { janode: janodeConfig, web: serverConfig } = config; + +import { fileURLToPath } from 'url'; +import { dirname, basename } from 'path'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const { Logger } = Janode; +const LOG_NS = `[${basename(__filename)}]`; +import VideoRoomPlugin from '../../../src/plugins/videoroom-plugin.js'; + +import express from 'express'; +const app = express(); +const options = { + key: serverConfig.key ? readFileSync(serverConfig.key) : null, + cert: serverConfig.cert ? readFileSync(serverConfig.cert) : null, +}; +import { createServer as createHttpsServer } from 'https'; +import { createServer as createHttpServer } from 'http'; +const httpServer = (options.key && options.cert) ? createHttpsServer(options, app) : createHttpServer(app); +import { Server } from 'socket.io'; +const io = new Server(httpServer); + +const scheduleBackEndConnection = (function () { + let task = null; + + return (function (del = 10) { + if (task) return; + Logger.info(`${LOG_NS} scheduled connection in ${del} seconds`); + task = setTimeout(() => { + initBackEnd() + .then(() => task = null) + .catch(() => { + task = null; + scheduleBackEndConnection(); + }); + }, del * 1000); + }); +})(); + +let janodeSession; +let janodeManagerHandle; + +(function main() { + + initFrontEnd().catch(({ message }) => Logger.error(`${LOG_NS} failure initializing front-end: ${message}`)); + + scheduleBackEndConnection(1); + +})(); + +async function initBackEnd() { + Logger.info(`${LOG_NS} connecting Janode...`); + let connection; + + try { + connection = await Janode.connect(janodeConfig); + Logger.info(`${LOG_NS} connection with Janus created`); + + connection.once(Janode.EVENT.CONNECTION_CLOSED, () => { + Logger.info(`${LOG_NS} connection with Janus closed`); + }); + + connection.once(Janode.EVENT.CONNECTION_ERROR, error => { + Logger.error(`${LOG_NS} connection with Janus error: ${error.message}`); + + replyError(io, 'backend-failure'); + + scheduleBackEndConnection(); + }); + + const session = await connection.create(); + Logger.info(`${LOG_NS} session ${session.id} with Janus created`); + janodeSession = session; + + session.once(Janode.EVENT.SESSION_DESTROYED, () => { + Logger.info(`${LOG_NS} session ${session.id} destroyed`); + janodeSession = null; + }); + + const handle = await session.attach(VideoRoomPlugin); + Logger.info(`${LOG_NS} manager handle ${handle.id} attached`); + janodeManagerHandle = handle; + + // generic handle events + handle.once(Janode.EVENT.HANDLE_DETACHED, () => { + Logger.info(`${LOG_NS} ${handle.name} manager handle detached event`); + }); + } + catch (error) { + Logger.error(`${LOG_NS} Janode setup error: ${error.message}`); + if (connection) connection.close().catch(() => { }); + + // notify clients + replyError(io, 'backend-failure'); + + throw error; + } +} + +function initFrontEnd() { + if (httpServer.listening) return Promise.reject(new Error('Server already listening')); + + Logger.info(`${LOG_NS} initializing socketio front end...`); + + io.on('connection', function (socket) { + const remote = `[${socket.request.connection.remoteAddress}:${socket.request.connection.remotePort}]`; + Logger.info(`${LOG_NS} ${remote} connection with client established`); + + const msHandles = (function () { + const handles = { + pub: null, + sub: null, + }; + + return { + setPubHandle: handle => { + handles.pub = handle; + }, + setSubHandle: handle => { + handles.sub = handle; + }, + getPubHandle: _ => { + return handles.pub; + }, + getSubHandle: _ => { + return handles.sub; + }, + getHandleByFeed: feed => { + if (feed && handles.pub && feed === handles.pub.feed) return handles.pub; + if (!feed && handles.sub) return handles.sub; + return null; + }, + detachPubHandle: async _ => { + if (handles.pub) + await handles.pub.detach().catch(() => { }); + handles.pub = null; + }, + detachSubHandle: async _ => { + if (handles.sub) + await handles.sub.detach().catch(() => { }); + handles.sub = null; + }, + detachAll: async _ => { + const detaches = Object.values(handles).map(h => h && h.detach().catch(() => { })); + await Promise.all(detaches); + handles.pub = null; + handles.sub = null; + }, + }; + })(); + + /*----------*/ + /* USER API */ + /*----------*/ + + socket.on('join', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} join received`); + const { _id, data: joindata = {} } = evtdata; + + if (!checkSessions(janodeSession, true, socket, evtdata)) return; + + let pubHandle; + + try { + pubHandle = await janodeSession.attach(VideoRoomPlugin); + Logger.info(`${LOG_NS} ${remote} videoroom publisher handle ${pubHandle.id} attached`); + msHandles.setPubHandle(pubHandle); + + // custom videoroom publisher/manager events + + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_DESTROYED, evtdata => { + replyEvent(socket, 'destroyed', evtdata); + }); + + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_PUB_LIST, evtdata => { + replyEvent(socket, 'feed-list', evtdata); + }); + + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_PUB_PEER_JOINED, evtdata => { + replyEvent(socket, 'feed-joined', evtdata); + }); + + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_UNPUBLISHED, evtdata => { + replyEvent(socket, 'unpublished', evtdata); + }); + + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_LEAVING, async evtdata => { + if (pubHandle.feed === evtdata.feed) { + await msHandles.detachPubHandle(); + } + replyEvent(socket, 'leaving', evtdata); + }); + + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_DISPLAY, evtdata => { + replyEvent(socket, 'display', evtdata); + }); + + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_TALKING, evtdata => { + replyEvent(socket, 'talking', evtdata); + }); + + pubHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_KICKED, async evtdata => { + replyEvent(socket, 'kicked', evtdata); + }); + + // generic videoroom events + pubHandle.on(Janode.EVENT.HANDLE_WEBRTCUP, () => Logger.info(`${LOG_NS} ${pubHandle.name} webrtcup event`)); + pubHandle.on(Janode.EVENT.HANDLE_MEDIA, evtdata => Logger.info(`${LOG_NS} ${pubHandle.name} media event ${JSON.stringify(evtdata)}`)); + pubHandle.on(Janode.EVENT.HANDLE_SLOWLINK, evtdata => Logger.info(`${LOG_NS} ${pubHandle.name} slowlink event ${JSON.stringify(evtdata)}`)); + pubHandle.on(Janode.EVENT.HANDLE_HANGUP, evtdata => Logger.info(`${LOG_NS} ${pubHandle.name} hangup event ${JSON.stringify(evtdata)}`)); + pubHandle.on(Janode.EVENT.HANDLE_DETACHED, () => { + Logger.info(`${LOG_NS} ${pubHandle.name} detached event`); + msHandles.setPubHandle(null); + }); + pubHandle.on(Janode.EVENT.HANDLE_TRICKLE, evtdata => Logger.info(`${LOG_NS} ${pubHandle.name} trickle event ${JSON.stringify(evtdata)}`)); + + const response = await pubHandle.joinPublisher(joindata); + + replyEvent(socket, 'joined', response, _id); + + Logger.info(`${LOG_NS} ${remote} joined sent`); + } catch ({ message }) { + if (pubHandle) pubHandle.detach().catch(() => { }); + replyError(socket, message, joindata, _id); + } + }); + + socket.on('subscribe', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} subscribe received`); + const { _id, data: subscribedata = {} } = evtdata; + + if (!checkSessions(janodeSession, true, socket, evtdata)) return; + + let subHandle = msHandles.getSubHandle(); + let response; + + try { + if (!subHandle) { + subHandle = await janodeSession.attach(VideoRoomPlugin); + Logger.info(`${LOG_NS} ${remote} videoroom listener handle ${subHandle.id} attached`); + msHandles.setSubHandle(subHandle); + // generic videoroom events + subHandle.on(Janode.EVENT.HANDLE_WEBRTCUP, () => Logger.info(`${LOG_NS} ${subHandle.name} webrtcup event`)); + subHandle.on(Janode.EVENT.HANDLE_SLOWLINK, evtdata => Logger.info(`${LOG_NS} ${subHandle.name} slowlink event ${JSON.stringify(evtdata)}`)); + subHandle.on(Janode.EVENT.HANDLE_HANGUP, evtdata => Logger.info(`${LOG_NS} ${subHandle.name} hangup event ${JSON.stringify(evtdata)}`)); + subHandle.once(Janode.EVENT.HANDLE_DETACHED, () => { + Logger.info(`${LOG_NS} ${subHandle.name} detached event`); + msHandles.setSubHandle(null); + }); + subHandle.on(Janode.EVENT.HANDLE_TRICKLE, evtdata => Logger.info(`${LOG_NS} ${subHandle.name} trickle event ${JSON.stringify(evtdata)}`)); + + // specific videoroom events + subHandle.on(VideoRoomPlugin.EVENT.VIDEOROOM_UPDATED, evtdata => { + Logger.info(`${LOG_NS} ${subHandle.name} updated event`); + replyEvent(socket, 'updated', evtdata); + }); + response = await subHandle.joinSubscriber(subscribedata); + } + else { + response = await subHandle.update({ + subscribe: subscribedata.streams, + }); + } + + replyEvent(socket, 'subscribed', response, _id); + Logger.info(`${LOG_NS} ${remote} subscribed sent`); + } catch ({ message }) { + replyError(socket, message, subscribedata, _id); + } + }); + + socket.on('unsubscribe', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} unsubscribe received`); + const { _id, data: unsubscribedata = {} } = evtdata; + + let subHandle = msHandles.getSubHandle(); + if (!checkSessions(janodeSession, subHandle, socket, evtdata)) return; + let response; + + try { + response = await subHandle.update({ + unsubscribe: unsubscribedata.streams, + }); + + replyEvent(socket, 'unsubscribed', response, _id); + Logger.info(`${LOG_NS} ${remote} unsubscribed sent`); + } catch ({ message }) { + replyError(socket, message, unsubscribedata, _id); + } + }); + + socket.on('configure', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} configure received`); + const { _id, data: confdata = {} } = evtdata; + + const handle = msHandles.getHandleByFeed(confdata.feed); + if (!checkSessions(janodeSession, handle, socket, evtdata)) return; + + try { + const response = await handle.configure(confdata); + delete response.configured; + replyEvent(socket, 'configured', response, _id); + Logger.info(`${LOG_NS} ${remote} configured sent`); + } catch ({ message }) { + replyError(socket, message, confdata, _id); + } + }); + + socket.on('unpublish', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} unpublish received`); + const { _id, data: unpubdata = {} } = evtdata; + + const handle = msHandles.getPubHandle(); + if (!checkSessions(janodeSession, handle, socket, evtdata)) return; + + try { + const response = await handle.unpublish(); + replyEvent(socket, 'unpublished', response, _id); + Logger.info(`${LOG_NS} ${remote} unpublished sent`); + } catch ({ message }) { + replyError(socket, message, unpubdata, _id); + } + }); + + socket.on('leave', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} leave received`); + const { _id, data: leavedata = {} } = evtdata; + + const handle = msHandles.getHandleByFeed(leavedata.feed); + if (!checkSessions(janodeSession, handle, socket, evtdata)) return; + + try { + const response = await handle.leave(); + replyEvent(socket, 'leaving', response, _id); + Logger.info(`${LOG_NS} ${remote} leaving sent`); + handle.detach().catch(() => { }); + } catch ({ message }) { + replyError(socket, message, leavedata, _id); + } + }); + + socket.on('start', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} start received`); + const { _id, data: startdata = {} } = evtdata; + + const handle = msHandles.getSubHandle(); + if (!checkSessions(janodeSession, handle, socket, evtdata)) return; + + try { + const response = await handle.start(startdata); + replyEvent(socket, 'started', response, _id); + Logger.info(`${LOG_NS} ${remote} started sent`); + } catch ({ message }) { + replyError(socket, message, startdata, _id); + } + }); + + socket.on('pause', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} pause received`); + const { _id, data: pausedata = {} } = evtdata; + + const handle = msHandles.getSubHandle(); + if (!checkSessions(janodeSession, handle, socket, evtdata)) return; + + try { + const response = await handle.pause(); + replyEvent(socket, 'paused', response, _id); + Logger.info(`${LOG_NS} ${remote} paused sent`); + } catch ({ message }) { + replyError(socket, message, pausedata, _id); + } + }); + + socket.on('switch', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} switch received`); + const { _id, data: switchdata = {} } = evtdata; + + const handle = msHandles.getSubHandle(); + if (!checkSessions(janodeSession, handle, socket, evtdata)) return; + + try { + const response = await handle.switch(switchdata); + replyEvent(socket, 'switched', response, _id); + Logger.info(`${LOG_NS} ${remote} switched sent`); + } catch ({ message }) { + replyError(socket, message, switchdata, _id); + } + }); + + // trickle candidate from the client + socket.on('trickle', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} trickle received`); + const { _id, data: trickledata = {} } = evtdata; + + const handle = msHandles.getHandleByFeed(trickledata.feed); + if (!checkSessions(janodeSession, handle, socket, evtdata)) return; + + handle.trickle(trickledata.candidate).catch(({ message }) => replyError(socket, message, trickledata, _id)); + }); + + // trickle complete signal from the client + socket.on('trickle-complete', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} trickle-complete received`); + const { _id, data: trickledata = {} } = evtdata; + + const handle = msHandles.getHandleByFeed(trickledata.feed); + if (!checkSessions(janodeSession, handle, socket, evtdata)) return; + + handle.trickleComplete(trickledata.candidate).catch(({ message }) => replyError(socket, message, trickledata, _id)); + }); + + // socket disconnection event + socket.on('disconnect', async () => { + Logger.info(`${LOG_NS} ${remote} disconnected socket`); + + await msHandles.detachAll(); + }); + + + /*----------------*/ + /* Management API */ + /*----------------*/ + + + socket.on('list-participants', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} list_participants received`); + const { _id, data: listdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.listParticipants(listdata); + replyEvent(socket, 'participants-list', response, _id); + Logger.info(`${LOG_NS} ${remote} participants-list sent`); + } catch ({ message }) { + replyError(socket, message, listdata, _id); + } + }); + + socket.on('kick', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} kick received`); + const { _id, data: kickdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.kick(kickdata); + replyEvent(socket, 'kicked', response, _id); + Logger.info(`${LOG_NS} ${remote} kicked sent`); + } catch ({ message }) { + replyError(socket, message, kickdata, _id); + } + }); + + socket.on('exists', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} exists received`); + const { _id, data: existsdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.exists(existsdata); + replyEvent(socket, 'exists', response, _id); + Logger.info(`${LOG_NS} ${remote} exists sent`); + } catch ({ message }) { + replyError(socket, message, existsdata, _id); + } + }); + + socket.on('list-rooms', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} list-rooms received`); + const { _id, data: listdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.list(); + replyEvent(socket, 'rooms-list', response, _id); + Logger.info(`${LOG_NS} ${remote} rooms-list sent`); + } catch ({ message }) { + replyError(socket, message, listdata, _id); + } + }); + + socket.on('create', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} create received`); + const { _id, data: createdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.create(createdata); + replyEvent(socket, 'created', response, _id); + Logger.info(`${LOG_NS} ${remote} created sent`); + } catch ({ message }) { + replyError(socket, message, createdata, _id); + } + }); + + socket.on('destroy', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} destroy received`); + const { _id, data: destroydata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.destroy(destroydata); + replyEvent(socket, 'destroyed', response, _id); + Logger.info(`${LOG_NS} ${remote} destroyed sent`); + } catch ({ message }) { + replyError(socket, message, destroydata, _id); + } + }); + + socket.on('allow', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} allow received`); + const { _id, data: allowdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.allow(allowdata); + replyEvent(socket, 'allowed', response, _id); + Logger.info(`${LOG_NS} ${remote} allowed sent`); + } catch ({ message }) { + replyError(socket, message, allowdata, _id); + } + }); + + socket.on('rtp-fwd-start', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} rtp-fwd-start received`); + const { _id, data: rtpstartdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.startForward(rtpstartdata); + replyEvent(socket, 'rtp-fwd-started', response, _id); + Logger.info(`${LOG_NS} ${remote} rtp-fwd-started sent`); + } catch ({ message }) { + replyError(socket, message, rtpstartdata, _id); + } + }); + + socket.on('rtp-fwd-stop', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} rtp-fwd-stop received`); + const { _id, data: rtpstopdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.stopForward(rtpstopdata); + replyEvent(socket, 'rtp-fwd-stopped', response, _id); + Logger.info(`${LOG_NS} ${remote} rtp-fwd-stopped sent`); + } catch ({ message }) { + replyError(socket, message, rtpstopdata, _id); + } + }); + + socket.on('rtp-fwd-list', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} rtp_fwd_list received`); + const { _id, data: rtplistdata = {} } = evtdata; + + if (!checkSessions(janodeSession, janodeManagerHandle, socket, evtdata)) return; + + try { + const response = await janodeManagerHandle.listForward(rtplistdata); + replyEvent(socket, 'rtp-fwd-list', response, _id); + Logger.info(`${LOG_NS} ${remote} rtp-fwd-list sent`); + } catch ({ message }) { + replyError(socket, message, rtplistdata, _id); + } + }); + + }); + + // disable caching for all app + app.set('etag', false).set('view cache', false); + + // static content + app.use('/janode', express.static(__dirname + '/../html/', { + etag: false, + lastModified: false, + maxAge: 0, + })); + + // http server binding + return new Promise((resolve, reject) => { + // web server binding + httpServer.listen( + serverConfig.port, + serverConfig.bind, + () => { + Logger.info(`${LOG_NS} server listening on ${(options.key && options.cert) ? 'https' : 'http'}://${serverConfig.bind}:${serverConfig.port}/janode`); + resolve(); + } + ); + + httpServer.on('error', e => reject(e)); + }); +} + +function checkSessions(session, handle, socket, { data, _id }) { + if (!session) { + replyError(socket, 'session-not-available', data, _id); + return false; + } + if (!handle) { + replyError(socket, 'handle-not-available', data, _id); + return false; + } + return true; +} + +function replyEvent(socket, evtname, data, _id) { + const evtdata = { + data, + }; + if (_id) evtdata._id = _id; + + socket.emit(evtname, evtdata); +} + +function replyError(socket, message, request, _id) { + const evtdata = { + error: message, + }; + if (request) evtdata.request = request; + if (_id) evtdata._id = _id; + + socket.emit('videoroom-error', evtdata); +} diff --git a/src/handle.js b/src/handle.js index 92ac64d..56edebd 100644 --- a/src/handle.js +++ b/src/handle.js @@ -294,6 +294,9 @@ class Handle extends EventEmitter { case JANUS.EVENT.MEDIA: { if (typeof janus_message.type !== 'undefined') janode_event_data.type = janus_message.type; if (typeof janus_message.receiving !== 'undefined') janode_event_data.receiving = janus_message.receiving; + if (typeof janus_message.mid !== 'undefined') janode_event_data.mid = janus_message.mid; + if (typeof janus_message.substream !== 'undefined') janode_event_data.substream = janus_message.substream; + if (typeof janus_message.seconds !== 'undefined') janode_event_data.substream = janus_message.seconds; /** * The handle received a media notification. * @@ -301,6 +304,9 @@ class Handle extends EventEmitter { * @type {object} * @property {string} type - The kind of media (audio/video) * @property {boolean} receiving - True if Janus is receiving media + * @property {string} [mid] - The involved mid + * @property {number} [substream] - The involved simulcast substream + * @property {number} [seconds] - Time, in seconds, with no media */ this.emit(JANODE.EVENT.HANDLE_MEDIA, janode_event_data); break; @@ -321,14 +327,18 @@ class Handle extends EventEmitter { /* In this case the janus message has "uplink" and "nacks" fields */ case JANUS.EVENT.SLOWLINK: { if (typeof janus_message.uplink !== 'undefined') janode_event_data.uplink = janus_message.uplink; - if (typeof janus_message.nacks !== 'undefined') janode_event_data.nacks = janus_message.nacks; + if (typeof janus_message.mid !== 'undefined') janode_event_data.mid = janus_message.mid; + if (typeof janus_message.media !== 'undefined') janode_event_data.media = janus_message.media; + if (typeof janus_message.lost !== 'undefined') janode_event_data.lost = janus_message.lost; /** * The handle has received a slowlink notification. * * @event module:handle~Handle#event:HANDLE_SLOWLINK * @type {object} * @property {boolean} uplink - The direction of the slow link - * @property {number} nacks - Number of nacks in the last time slot + * @property {string} media - The media kind (audio/video) + * @property {string} [mid] - The involved stream mid + * @property {number} lost - Number of missing packets in the last time slot */ this.emit(JANODE.EVENT.HANDLE_SLOWLINK, janode_event_data); break; diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 805bf23..b448aa6 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -98,6 +98,14 @@ class VideoRoomHandle extends Handle { */ this.feed = null; + /** + * [multistream] + * Either the streams assigned to this publisher handle or the streams subscribed to in case this handle is a subscriber. + * + * @type {object[]} + */ + this.streams = null; + /** * The identifier of the videoroom the handle has joined. * @@ -205,18 +213,24 @@ class VideoRoomHandle extends Handle { case 'attached': /* Store room and feed id */ this.room = room; - this.feed = message_data.id; + if (typeof message_data.id !== 'undefined') { + this.feed = message_data.id; + janode_event.data.feed = message_data.id; + janode_event.data.display = message_data.display; + } - janode_event.data.feed = message_data.id; - janode_event.data.display = message_data.display; /* [multistream] add streams info to the subscriber joined event */ - if (typeof message_data.streams !== 'undefined') janode_event.data.streams = message_data.streams; + if (typeof message_data.streams !== 'undefined') { + this.streams = message_data.streams; + janode_event.data.streams = message_data.streams; + } + janode_event.event = PLUGIN_EVENT.SUB_JOINED; break; /* Slow-link event */ case 'slow_link': - janode_event.data.feed = this.feed; + if (this.feed) janode_event.data.feed = this.feed; janode_event.data.bitrate = message_data['current-bitrate']; janode_event.event = PLUGIN_EVENT.SLOW_LINK; break; @@ -249,31 +263,81 @@ class VideoRoomHandle extends Handle { /* RTP forwarding started */ case 'rtp_forward': janode_event.data.feed = message_data.publisher_id; - janode_event.data.forwarder = { - host: message_data.rtp_stream.host, - }; - if (message_data.rtp_stream.audio) { - janode_event.data.forwarder.audio_port = message_data.rtp_stream.audio; - janode_event.data.forwarder.audio_rtcp_port = message_data.rtp_stream.audio_rtcp; - janode_event.data.forwarder.audio_stream = message_data.rtp_stream.audio_stream_id; - } - if (message_data.rtp_stream.video) { - janode_event.data.forwarder.video_port = message_data.rtp_stream.video; - janode_event.data.forwarder.video_rtcp_port = message_data.rtp_stream.video_rtcp; - janode_event.data.forwarder.video_stream = message_data.rtp_stream.video_stream_id; - if (message_data.rtp_stream.video_stream_id_2) { - janode_event.data.forwarder.video_port_2 = message_data.rtp_stream.video_2; - janode_event.data.forwarder.video_stream_2 = message_data.rtp_stream.video_stream_id_2; + if (message_data.rtp_stream) { + const f = message_data.rtp_stream; + const fwd = { + host: f.host, + }; + if (f.audio_stream_id) { + fwd.audio_stream = f.audio_stream_id; + fwd.audio_port = f.audio; + if (typeof f.audio_rtcp === 'number') { + fwd.audio_rtcp_port = f.audio_rtcp; + } + } + if (f.video_stream_id) { + fwd.video_stream = f.video_stream_id; + fwd.video_port = f.video; + if (typeof f.video_rtcp === 'number') { + fwd.video_rtcp_port = f.video_rtcp; + } + if (f.video_stream_id_2) { + fwd.video_stream_2 = f.video_stream_id_2; + fwd.video_port_2 = f.video_2; + } + if (f.video_stream_id_3) { + fwd.video_stream_3 = f.video_stream_id_3; + fwd.video_port_3 = f.video_3; + } } - if (message_data.rtp_stream.video_stream_id_3) { - janode_event.data.forwarder.video_port_3 = message_data.rtp_stream.video_3; - janode_event.data.forwarder.video_stream_3 = message_data.rtp_stream.video_stream_id_3; + if (f.data_stream_id) { + fwd.data_stream = f.data_stream_id; + fwd.data_port = f.data; } + + janode_event.data.forwarder = fwd; } - if (message_data.rtp_stream.data) { - janode_event.data.forwarder.data_port = message_data.rtp_stream.data; - janode_event.data.forwarder.data_stream = message_data.rtp_stream.data_stream_id; + /* [multistream] */ + else if (message_data.forwarders) { + janode_event.data.forwarders = message_data.forwarders.map(f => { + const fwd = { + host: f.host, + }; + if (f.type === 'audio') { + fwd.audio_stream = f.stream_id; + fwd.audio_port = f.port; + if (typeof f.remote_rtcp_port === 'number') { + fwd.audio_rtcp_port = f.remote_rtcp_port; + } + } + if (f.type === 'video') { + fwd.video_stream = f.stream_id; + fwd.video_port = f.port; + if (typeof f.remote_rtcp_port === 'number') { + fwd.video_rtcp_port = f.remote_rtcp_port; + } + if (typeof f.substream === 'number') { + fwd.sc_substream_layer = f.substream; + } + } + if (f.type === 'data') { + fwd.data_stream = f.stream_id; + fwd.data_port = f.port; + } + if (typeof f.ssrc === 'number') { + fwd.ssrc = f.ssrc; + } + if (typeof f.pt === 'number') { + fwd.pt = f.pt; + } + if (typeof f.srtp === 'boolean') { + fwd.srtp = f.srtp; + } + + return fwd; + }); } + janode_event.event = PLUGIN_EVENT.RTP_FWD_STARTED; break; @@ -292,69 +356,89 @@ class VideoRoomHandle extends Handle { feed: publisher_id, }; - pub.forwarders = rtp_forwarder.map(forw => { - const forwarder = { - host: forw.ip, + pub.forwarders = rtp_forwarder.map(f => { + const fwd = { + host: f.ip, }; - - if (forw.audio_stream_id) { - forwarder.audio_port = forw.port; - forwarder.audio_rtcp_port = forw.remote_rtcp_port; - forwarder.audio_stream = forw.audio_stream_id; + if (f.audio_stream_id) { + fwd.audio_stream = f.audio_stream_id; + fwd.audio_port = f.port; + if (typeof f.remote_rtcp_port === 'number') { + fwd.audio_rtcp_port = f.remote_rtcp_port; + } + } + if (f.video_stream_id) { + fwd.video_stream = f.video_stream_id; + fwd.video_port = f.port; + if (typeof f.remote_rtcp_port === 'number') { + fwd.video_rtcp_port = f.remote_rtcp_port; + } + if (typeof f.substream === 'number') { + fwd.sc_substream_layer = f.substream; + } } - if (forw.video_stream_id) { - forwarder.video_port = forw.port; - forwarder.video_rtcp_port = forw.remote_rtcp_port; - forwarder.video_stream = forw.video_stream_id; + if (f.data_stream_id) { + fwd.data_stream = f.data_stream_id; + fwd.data_port = f.port; } - if (forw.data_stream_id) { - forwarder.data_port = forw.port; - forwarder.data_stream = forw.data_stream_id; + if (typeof f.ssrc === 'number') { + fwd.ssrc = f.ssrc; + } + if (typeof f.pt === 'number') { + fwd.pt = f.pt; + } + if (typeof f.srtp === 'boolean') { + fwd.srtp = f.srtp; } - return forwarder; + return fwd; }); return pub; }); } + /* [multistream] */ else if (message_data.publishers) { janode_event.data.forwarders = message_data.publishers.map(({ publisher_id, forwarders }) => { const pub = { feed: publisher_id, }; - pub.forwarders = forwarders.map(forw => { - const forwarder = { - host: forw.host, + pub.forwarders = forwarders.map(f => { + const fwd = { + host: f.host, }; - - if (forw.type === 'audio') { - forwarder.audio_port = forw.port; - forwarder.audio_rtcp_port = forw.remote_rtcp_port; - forwarder.audio_stream = forw.stream_id; + if (f.type === 'audio') { + fwd.audio_stream = f.stream_id; + fwd.audio_port = f.port; + if (typeof f.remote_rtcp_port === 'number') { + fwd.audio_rtcp_port = f.remote_rtcp_port; + } } - if (forw.type === 'video') { - forwarder.video_port = forw.port; - forwarder.video_rtcp_port = forw.remote_rtcp_port; - forwarder.video_stream = forw.stream_id; - if (typeof forw.substream !== 'undefined') { - forwarder.sc_substream_layer = forw.substream; + if (f.type === 'video') { + fwd.video_stream = f.stream_id; + fwd.video_port = f.port; + if (typeof f.remote_rtcp_port === 'number') { + fwd.video_rtcp_port = f.remote_rtcp_port; + } + if (typeof f.substream === 'number') { + fwd.sc_substream_layer = f.substream; } } - if (forw.type === 'data') { - forwarder.data_port = forw.port; - forwarder.data_stream = forw.stream_id; + if (f.type === 'data') { + fwd.data_stream = f.stream_id; + fwd.data_port = f.port; } - - if (typeof forw.ssrc !== 'undefined') - forwarder.ssrc = forw.ssrc; - if (typeof forw.pt !== 'undefined') - forwarder.pt = forw.pt; - if (typeof forw.srtp !== 'undefined') - forwarder.srtp = forw.srtp; - - return forwarder; + if (typeof f.ssrc === 'number') { + fwd.ssrc = f.ssrc; + } + if (typeof f.pt === 'number') { + fwd.pt = f.pt; + } + if (typeof f.srtp === 'boolean') { + fwd.srtp = f.srtp; + } + return fwd; }); return pub; @@ -369,6 +453,8 @@ class VideoRoomHandle extends Handle { case 'stopped-talking': janode_event.data.feed = message_data.id; janode_event.data.talking = (videoroom === 'talking'); + /* [multistream] */ + if (typeof message_data.mid !== 'undefined') janode_event.data.mid = message_data.mid; janode_event.data.audio_level = message_data['audio-level-dBov-avg']; janode_event.event = PLUGIN_EVENT.TALKING; break; @@ -424,7 +510,7 @@ class VideoRoomHandle extends Handle { /* Configuration events (publishing, general configuration) */ if (typeof message_data.configured !== 'undefined') { janode_event.event = PLUGIN_EVENT.CONFIGURED; - janode_event.data.feed = this.feed; + if (this.feed) janode_event.data.feed = this.feed; /* [multistream] add streams info */ if (typeof message_data.streams !== 'undefined') janode_event.data.streams = message_data.streams; janode_event.data.configured = message_data.configured; @@ -440,14 +526,14 @@ class VideoRoomHandle extends Handle { /* Subscribed feed started */ if (typeof message_data.started !== 'undefined') { janode_event.event = PLUGIN_EVENT.STARTED; - janode_event.data.feed = this.feed; + if (this.feed) janode_event.data.feed = this.feed; janode_event.data.started = message_data.started; break; } /* Subscribed feed paused */ if (typeof message_data.paused !== 'undefined') { janode_event.event = PLUGIN_EVENT.PAUSED; - janode_event.data.feed = this.feed; + if (this.feed) janode_event.data.feed = this.feed; janode_event.data.paused = message_data.paused; break; } @@ -455,11 +541,17 @@ class VideoRoomHandle extends Handle { if (typeof message_data.switched !== 'undefined') { janode_event.event = PLUGIN_EVENT.SWITCHED; janode_event.data.switched = message_data.switched; - if (message_data.switched === 'ok' && typeof message_data.id !== 'undefined') { - janode_event.data.from_feed = this.feed; - this.feed = message_data.id; - janode_event.data.to_feed = this.feed; - janode_event.data.display = message_data.display; + if (message_data.switched === 'ok') { + if (typeof message_data.id !== 'undefined') { + janode_event.data.from_feed = this.feed; + this.feed = message_data.id; + janode_event.data.to_feed = this.feed; + janode_event.data.display = message_data.display; + } + if (typeof message_data.streams != 'undefined') { + this.streams = message_data.streams; + janode_event.data.streams = message_data.streams; + } } break; } @@ -485,20 +577,24 @@ class VideoRoomHandle extends Handle { /* Participant left (for subscribers "leave") */ if (typeof message_data.left !== 'undefined') { janode_event.event = PLUGIN_EVENT.LEAVING; - janode_event.data.feed = this.feed; + if (this.feed) janode_event.data.feed = this.feed; break; } /* Simulcast substream layer switch */ if (typeof message_data.substream !== 'undefined') { janode_event.event = PLUGIN_EVENT.SC_SUBSTREAM_LAYER; - janode_event.data.feed = this.feed; + if (this.feed) janode_event.data.feed = this.feed; + /* [multistream] */ + if (typeof message_data.mid !== 'undefined') janode_event.data.mid = message_data.mid; janode_event.data.sc_substream_layer = message_data.substream; break; } /* Simulcast temporal layers switch */ if (typeof message_data.temporal !== 'undefined') { janode_event.event = PLUGIN_EVENT.SC_TEMPORAL_LAYERS; - janode_event.data.feed = this.feed; + if (this.feed) janode_event.data.feed = this.feed; + /* [multistream] */ + if (typeof message_data.mid !== 'undefined') janode_event.data.mid = message_data.mid; janode_event.data.sc_temporal_layers = message_data.temporal; break; } @@ -539,9 +635,10 @@ class VideoRoomHandle extends Handle { * @param {string} [params.pin] - The optional pin needed to join the room * @param {boolean} [params.record] - Enable the recording * @param {string} [params.filename] - If recording, the base path/file to use for the recording + * @param {object[]} [params.descriptions] - [multistream] The descriptions object, can define a description for the tracks separately e.g. track mid:0 'Video Camera', track mid:1 'Screen' * @returns {Promise} */ - async joinPublisher({ room, feed, audio, video, data, bitrate, record, filename, display, token, pin }) { + async joinPublisher({ room, feed, audio, video, data, bitrate, record, filename, display, token, pin, descriptions }) { const body = { request: REQUEST_JOIN, ptype: PTYPE_PUBLISHER, @@ -558,6 +655,9 @@ class VideoRoomHandle extends Handle { if (typeof token === 'string') body.token = token; if (typeof pin === 'string') body.pin = pin; + /* [multistream] */ + if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; + const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; if (event === PLUGIN_EVENT.PUB_JOINED) { @@ -584,10 +684,11 @@ class VideoRoomHandle extends Handle { * @param {boolean} [params.record] - Enable the recording * @param {string} [params.filename] - If recording, the base path/file to use for the recording * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection + * @param {object[]} [params.descriptions] - [multistream] The descriptions object, can define a description for the tracks separately e.g. track mid:0 'Video Camera', track mid:1 'Screen' * @param {RTCSessionDescription} [params.jsep] - The JSEP offer * @returns {Promise} */ - async joinConfigurePublisher({ room, feed, audio, video, data, bitrate, record, filename, display, token, pin, e2ee, jsep }) { + async joinConfigurePublisher({ room, feed, audio, video, data, bitrate, record, filename, display, token, pin, e2ee, descriptions, jsep }) { const body = { request: REQUEST_JOIN_CONFIGURE, ptype: PTYPE_PUBLISHER, @@ -605,6 +706,9 @@ class VideoRoomHandle extends Handle { if (typeof pin === 'string') body.pin = pin; if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; + /* [multistream] */ + if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; + const response = await this.message(body, jsep).catch(e => { /* Cleanup the WebRTC status in Janus in case of errors when publishing */ /* @@ -667,22 +771,31 @@ class VideoRoomHandle extends Handle { const body = { request: REQUEST_CONFIGURE, }; - if (typeof audio === 'boolean') body.audio = audio; - if (typeof video === 'boolean') body.video = video; - if (typeof data === 'boolean') body.data = data; + + /* [multistream] */ + if (streams && Array.isArray(streams)) { + body.streams = streams; + } + else { + if (typeof audio === 'boolean') body.audio = audio; + if (typeof video === 'boolean') body.video = video; + if (typeof data === 'boolean') body.data = data; + if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; + if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; + if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; + } + if (typeof bitrate === 'number') body.bitrate = bitrate; if (typeof record === 'boolean') body.record = record; if (typeof filename === 'string') body.filename = filename; if (typeof display === 'string') body.display = display; if (typeof restart === 'boolean') body.restart = restart; if (typeof update === 'boolean') body.update = update; - if (streams && Array.isArray(streams)) body.streams = streams; - if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; - if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; - if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; - if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; + /* [multistream] */ + if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; + const response = await this.message(body, jsep).catch(e => { /* Cleanup the WebRTC status in Janus in case of errors when publishing */ /* @@ -727,13 +840,12 @@ class VideoRoomHandle extends Handle { * @param {number} [params.bitrate] - Bitrate cap * @param {boolean} [params.record] - True to record the feed * @param {string} [params.filename] - If recording, the base path/file to use for the recording - * @param {object[]} [params.streams] - [multistream] The streams object, each stream includes type, mid, description, disabled, simulcast * @param {object[]} [params.descriptions] - [multistream] The descriptions object, for each stream you can define description * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection * @param {RTCSessionDescription} params.jsep - The JSEP offer * @returns {Promise} */ - async publish({ audio, video, data, bitrate, record, filename, display, streams, descriptions, e2ee, jsep }) { + async publish({ audio, video, data, bitrate, record, filename, display, descriptions, e2ee, jsep }) { if (typeof jsep === 'object' && jsep && jsep.type !== 'offer') { const error = new Error('jsep must be an offer'); return Promise.reject(error); @@ -741,17 +853,22 @@ class VideoRoomHandle extends Handle { const body = { request: REQUEST_PUBLISH, }; + if (typeof audio === 'boolean') body.audio = audio; if (typeof video === 'boolean') body.video = video; if (typeof data === 'boolean') body.data = data; + if (typeof bitrate === 'number') body.bitrate = bitrate; if (typeof record === 'boolean') body.record = record; if (typeof filename === 'string') body.filename = filename; if (typeof display === 'string') body.display = display; - if (streams && Array.isArray(streams)) body.streams = streams; - if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; + /* [multistream] */ + if (descriptions && Array.isArray(descriptions)) { + body.descriptions = descriptions; + } + const response = await this.message(body, jsep).catch(e => { /* Cleanup the WebRTC status in Janus in case of errors when publishing */ /* @@ -813,27 +930,38 @@ class VideoRoomHandle extends Handle { * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled + * @param {object[]} [params.streams] - [multistream] The streams object, each stream includes feed, mid, send, ... * @param {boolean} [params.autoupdate] - [multistream] Whether a new SDP offer is sent automatically when a subscribed publisher leaves + * @param {boolean} [params.use_msid] - [multistream] Whether subscriptions should include an msid that references the publisher * @param {string} [params.token] - The optional token needed * @returns {Promise} */ - async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, autoupdate, token }) { + async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, streams, autoupdate, use_msid, token }) { const body = { request: REQUEST_JOIN, ptype: PTYPE_LISTENER, room, - feed, }; - if (typeof audio === 'boolean') body.audio = audio; - if (typeof video === 'boolean') body.video = video; - if (typeof data === 'boolean') body.data = data; + + /* [multistream] */ + if (streams && Array.isArray(streams)) { + body.streams = streams; + } + else { + body.feed = feed; + if (typeof audio === 'boolean') body.audio = audio; + if (typeof video === 'boolean') body.video = video; + if (typeof data === 'boolean') body.data = data; + if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; + if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; + if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; + } if (typeof private_id === 'number') body.private_id = private_id; if (typeof token === 'string') body.token = token; - if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; - if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; - if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; + /* [multistream] */ if (typeof autoupdate === 'boolean') body.autoupdate = autoupdate; + if (typeof use_msid === 'boolean') body.use_msid = use_msid; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; @@ -864,7 +992,8 @@ class VideoRoomHandle extends Handle { const body = { request: REQUEST_START, }; - jsep.e2ee = (typeof e2ee === 'boolean') ? e2ee : jsep.e2ee; + if (jsep) + jsep.e2ee = (typeof e2ee === 'boolean') ? e2ee : jsep.e2ee; const response = await this.message(body, jsep); const { event, data: evtdata } = response._janode || {}; @@ -896,20 +1025,28 @@ class VideoRoomHandle extends Handle { * Switch to another feed. * * @param {object} params - * @param {number|string} params.to_feed - The feed id of the new publisher to switch to + * @param {number|string} [params.to_feed] - The feed id of the new publisher to switch to * @param {boolean} [params.audio] - True to subscribe to the audio feed * @param {boolean} [params.video] - True to subscribe to the video feed * @param {boolean} [params.data] - True to subscribe to the datachannels of the feed + * @param {object[]} [params.streams] - [multistream] streams array containing feed, mid, sub_mid ... * @returns {Promise} */ - async switch({ to_feed, audio, video, data }) { + async switch({ to_feed, audio, video, data, streams }) { const body = { request: REQUEST_SWITCH, - feed: to_feed, }; - if (typeof audio === 'boolean') body.audio = audio; - if (typeof video === 'boolean') body.video = video; - if (typeof data === 'boolean') body.data = data; + + /* [multistream] */ + if (streams && Array.isArray(streams)) { + body.streams = streams; + } + else { + body.feed = to_feed; + if (typeof audio === 'boolean') body.audio = audio; + if (typeof video === 'boolean') body.video = video; + if (typeof data === 'boolean') body.data = data; + } const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; @@ -951,8 +1088,8 @@ class VideoRoomHandle extends Handle { const body = { request: REQUEST_UPDATE, }; - if (Array.isArray(subscribe)) body.subscribe = subscribe; - if (Array.isArray(unsubscribe)) body.unsubscribe = unsubscribe; + if (subscribe && Array.isArray(subscribe)) body.subscribe = subscribe; + if (unsubscribe && Array.isArray(unsubscribe)) body.unsubscribe = unsubscribe; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; @@ -1215,6 +1352,7 @@ class VideoRoomHandle extends Handle { * @param {number|string} params.room - The room where to start a forwarder * @param {number|string} params.feed - The feed identifier to forward (must be published) * @param {string} params.host - The target host for the forwarder + * @param {object[]} [params.streams] - [multistream] The streams array containing mid, port, rtcp_port, port_2 ... * @param {number} [params.audio_port] - The target audio RTP port, if audio is to be forwarded * @param {number} [params.audio_rtcp_port] - The target audio RTCP port, if audio is to be forwarded * @param {number} [params.audio_ssrc] - The SSRC that will be used for audio RTP @@ -1230,24 +1368,31 @@ class VideoRoomHandle extends Handle { * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ - async startForward({ room, feed, host, audio_port, audio_rtcp_port, audio_ssrc, video_port, video_rtcp_port, video_ssrc, video_port_2, video_ssrc_2, video_port_3, video_ssrc_3, data_port, secret, admin_key }) { + async startForward({ room, feed, host, streams, audio_port, audio_rtcp_port, audio_ssrc, video_port, video_rtcp_port, video_ssrc, video_port_2, video_ssrc_2, video_port_3, video_ssrc_3, data_port, secret, admin_key }) { const body = { request: REQUEST_RTP_FWD_START, room, publisher_id: feed, }; if (typeof host === 'string') body.host = host; - if (typeof audio_port === 'number') body.audio_port = audio_port; - if (typeof audio_rtcp_port === 'number') body.audio_rtcp_port = audio_rtcp_port; - if (typeof audio_ssrc === 'number') body.audio_ssrc = audio_ssrc; - if (typeof video_port === 'number') body.video_port = video_port; - if (typeof video_rtcp_port === 'number') body.video_rtcp_port = video_rtcp_port; - if (typeof video_ssrc === 'number') body.video_ssrc = video_ssrc; - if (typeof video_port_2 === 'number') body.video_port_2 = video_port_2; - if (typeof video_ssrc_2 === 'number') body.video_ssrc_2 = video_ssrc_2; - if (typeof video_port_3 === 'number') body.video_port_3 = video_port_3; - if (typeof video_ssrc_3 === 'number') body.video_ssrc_3 = video_ssrc_3; - if (typeof data_port === 'number') body.data_port = data_port; + /* [multistream] */ + if (streams && Array.isArray(streams)) { + body.streams = streams; + } + else { + if (typeof audio_port === 'number') body.audio_port = audio_port; + if (typeof audio_rtcp_port === 'number') body.audio_rtcp_port = audio_rtcp_port; + if (typeof audio_ssrc === 'number') body.audio_ssrc = audio_ssrc; + if (typeof video_port === 'number') body.video_port = video_port; + if (typeof video_rtcp_port === 'number') body.video_rtcp_port = video_rtcp_port; + if (typeof video_ssrc === 'number') body.video_ssrc = video_ssrc; + if (typeof video_port_2 === 'number') body.video_port_2 = video_port_2; + if (typeof video_ssrc_2 === 'number') body.video_ssrc_2 = video_ssrc_2; + if (typeof video_port_3 === 'number') body.video_port_3 = video_port_3; + if (typeof video_ssrc_3 === 'number') body.video_ssrc_3 = video_ssrc_3; + if (typeof data_port === 'number') body.data_port = data_port; + } + if (typeof secret === 'string') body.secret = secret; if (typeof admin_key === 'string') body.admin_key = admin_key; @@ -1347,8 +1492,8 @@ class VideoRoomHandle extends Handle { * * @typedef {object} VIDEOROOM_EVENT_SUB_JOINED * @property {number|string} room - The involved room - * @property {number|string} feed - The published feed identifier - * @property {string} display - The published feed display name + * @property {number|string} [feed] - The published feed identifier + * @property {string} [display] - The published feed display name * @property {object[]} [streams] - [multistream] Streams description as returned by Janus */ @@ -1416,7 +1561,8 @@ class VideoRoomHandle extends Handle { * * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_STARTED * @property {number|string} room - The involved room - * @property {RtpForwarder} forwarder - The forwarder object + * @property {RtpForwarder} [forwarder] - The forwarder object + * @property {RtpForwarder[]} [forwarders] - [multistream] The array of forwarders */ /** @@ -1472,7 +1618,7 @@ class VideoRoomHandle extends Handle { * * @typedef {object} VIDEOROOM_EVENT_STARTED * @property {number|string} room - The involved room - * @property {number|string} feed - The feed that started + * @property {number|string} [feed] - The feed that started * @property {boolean} [e2ee] - True if started stream is e2ee * @property {string} started - A string with the value returned by Janus */ @@ -1491,10 +1637,11 @@ class VideoRoomHandle extends Handle { * * @typedef {object} VIDEOROOM_EVENT_SWITCHED * @property {number|string} room - The involved room - * @property {number|string} from_feed - The feed that has been switched from - * @property {number|string} to_feed - The feed that has been switched to + * @property {number|string} [from_feed] - The feed that has been switched from + * @property {number|string} [to_feed] - The feed that has been switched to * @property {string} switched - A string with the value returned by Janus - * @property {string} display - The display name of the new feed + * @property {string} [display] - The display name of the new feed + * @property {object[]} [streams] - [multistream] The updated streams array */ /** From 4daf90fee498dc0a0528985884110ca77a4e889f Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 13 Jun 2024 14:07:47 +0200 Subject: [PATCH 061/114] handle: fix typo --- src/handle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handle.js b/src/handle.js index 56edebd..80c6578 100644 --- a/src/handle.js +++ b/src/handle.js @@ -296,7 +296,7 @@ class Handle extends EventEmitter { if (typeof janus_message.receiving !== 'undefined') janode_event_data.receiving = janus_message.receiving; if (typeof janus_message.mid !== 'undefined') janode_event_data.mid = janus_message.mid; if (typeof janus_message.substream !== 'undefined') janode_event_data.substream = janus_message.substream; - if (typeof janus_message.seconds !== 'undefined') janode_event_data.substream = janus_message.seconds; + if (typeof janus_message.seconds !== 'undefined') janode_event_data.seconds = janus_message.seconds; /** * The handle received a media notification. * From a05e767d0a372bf15a773efda1010c91106909e7 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 13 Jun 2024 14:08:55 +0200 Subject: [PATCH 062/114] version: bump to v1.7.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ba7dce3..44b98e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.6.11", + "version": "1.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.6.11", + "version": "1.7.0", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index aca9685..799ce58 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.6.11", + "version": "1.7.0", "type": "module", "keywords": [ "janus", From b1439adc449e679295acf89aef8a60ef42e43e7f Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 8 Jul 2024 14:27:13 +0200 Subject: [PATCH 063/114] audiobridge: add codec param to join API (fixes #41) --- src/plugins/audiobridge-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index ef5c4f9..c610364 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -414,9 +414,10 @@ class AudioBridgeHandle extends Handle { * @param {module:audiobridge-plugin~RtpParticipant} [params.rtp_participant] - Set a descriptor object if you need a RTP participant * @param {string} [params.group] - The group to assign to this participant * @param {boolean} [params.generate_offer] - True to get Janus to send the SDP offer. + * @param {string} [params.codec] - The codec to be used among opus, pcma or pcmu (Janus will default to opus) * @returns {Promise} */ - async join({ room, feed, display, muted, pin, token, quality, volume, record, filename, suspended, pause_events, rtp_participant, group, generate_offer }) { + async join({ room, feed, display, muted, pin, token, quality, volume, record, filename, suspended, pause_events, rtp_participant, group, generate_offer, codec }) { const body = { request: REQUEST_JOIN, room, @@ -435,6 +436,7 @@ class AudioBridgeHandle extends Handle { if (typeof rtp_participant === 'object' && rtp_participant) body.rtp = rtp_participant; if (typeof group === 'string') body.group = group; if (typeof generate_offer === 'boolean') body.generate_offer = generate_offer; + if (typeof codec === 'string') body.codec = codec; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; From 75149c3d9f9effcf26eb02a45e79e6d885bf05f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Per=C5=BCy=C5=82o?= Date: Mon, 22 Jul 2024 12:32:57 +0200 Subject: [PATCH 064/114] Custom collision parameter in streaming plugin (#43) --- src/plugins/streaming-plugin.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index d6282ad..ee1bf80 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -560,9 +560,10 @@ class StreamingHandle extends Handle { * @param {boolean} [params.data.buffer] - Enable buffering of the datachannels * @param {number} [params.threads] - The number of helper threads used in this mp * @param {object} [params.metadata] - An opaque metadata to add to the mp + * @param {number} [params.collision] - The stream collision discarding time in number of milliseconds (0=disabled) * @returns {Promise} */ - async createRtpMountpoint({ id = 0, name, description, secret, pin, admin_key, permanent = false, is_private = false, e2ee = false, audio, video, data, threads, metadata }) { + async createRtpMountpoint({ id = 0, name, description, secret, pin, admin_key, permanent = false, is_private = false, e2ee = false, audio, video, data, threads, metadata, collision }) { const body = { request: REQUEST_CREATE, type: 'rtp', @@ -612,6 +613,7 @@ class StreamingHandle extends Handle { } if (typeof threads === 'number' && threads > 0) body.threads = threads; if (metadata) body.metadata = metadata; + if (typeof collision === 'number') body.collision = collision; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; @@ -751,4 +753,4 @@ export default { */ STREAMING_ERROR: PLUGIN_EVENT.ERROR, }, -}; \ No newline at end of file +}; From 8acce285c0f8fb0f0decf194169a83051876beeb Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 22 Jul 2024 12:34:18 +0200 Subject: [PATCH 065/114] version: bump to v1.7.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 44b98e9..24497f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.7.0", + "version": "1.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.7.0", + "version": "1.7.1", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index 799ce58..a263658 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.7.0", + "version": "1.7.1", "type": "module", "keywords": [ "janus", From 84b41b8d69c29794e4f467c8fad83309175b6c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Per=C5=BCy=C5=82o?= Date: Fri, 26 Jul 2024 08:17:14 +0200 Subject: [PATCH 066/114] Add missing keyframe parameter to videoroom configure (#44) --- src/plugins/videoroom-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index b448aa6..cafba0d 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -765,9 +765,10 @@ class VideoRoomHandle extends Handle { * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled (subscribers only) * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection * @param {RTCSessionDescription} [params.jsep] - The JSEP offer (publishers only) + * @param {boolean} [params.keyframe] - True to request a keyframe (publishers only) * @returns {Promise} */ - async configure({ audio, video, data, bitrate, record, filename, display, restart, update, streams, descriptions, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, e2ee, jsep }) { + async configure({ audio, video, data, bitrate, record, filename, display, restart, update, streams, descriptions, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, e2ee, jsep, keyframe }) { const body = { request: REQUEST_CONFIGURE, }; @@ -792,6 +793,7 @@ class VideoRoomHandle extends Handle { if (typeof restart === 'boolean') body.restart = restart; if (typeof update === 'boolean') body.update = update; if (typeof e2ee === 'boolean' && jsep) jsep.e2ee = e2ee; + if (typeof keyframe === 'boolean') body.keyframe = keyframe; /* [multistream] */ if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; From 5159a72cf66bfd2b0af69759de59b71761bdda55 Mon Sep 17 00:00:00 2001 From: Emil Date: Wed, 31 Jul 2024 00:56:14 +0300 Subject: [PATCH 067/114] Add support for permanent option in destroy mountpoint (#45) --- src/plugins/streaming-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index ee1bf80..acc1230 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -628,14 +628,16 @@ class StreamingHandle extends Handle { * * @param {object} params * @param {number|string} params.id + * @param {boolean} [params.permanent] * @param {string} [params.secret] * @returns {Promise} */ - async destroyMountpoint({ id, secret }) { + async destroyMountpoint({ id, permanent, secret }) { const body = { request: REQUEST_DESTROY, id, }; + if (typeof permanent === 'boolean') body.permanent = permanent; if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); From 4792d5b4ccb5fd6bc3969aa54835646a68a1efcf Mon Sep 17 00:00:00 2001 From: Sergey Slobodenyuk Date: Mon, 11 Nov 2024 13:22:54 +0500 Subject: [PATCH 068/114] videoroom: add missing pin parameter to joinSubscriber (#48) Co-authored-by: Sergey Slobodenyuk --- src/plugins/videoroom-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index cafba0d..e58e9ee 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -936,9 +936,10 @@ class VideoRoomHandle extends Handle { * @param {boolean} [params.autoupdate] - [multistream] Whether a new SDP offer is sent automatically when a subscribed publisher leaves * @param {boolean} [params.use_msid] - [multistream] Whether subscriptions should include an msid that references the publisher * @param {string} [params.token] - The optional token needed + * @param {string} [params.pin] - The optional password required to join the room * @returns {Promise} */ - async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, streams, autoupdate, use_msid, token }) { + async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, streams, autoupdate, use_msid, token, pin }) { const body = { request: REQUEST_JOIN, ptype: PTYPE_LISTENER, @@ -960,6 +961,7 @@ class VideoRoomHandle extends Handle { } if (typeof private_id === 'number') body.private_id = private_id; if (typeof token === 'string') body.token = token; + if (typeof pin === 'string') body.pin = pin; /* [multistream] */ if (typeof autoupdate === 'boolean') body.autoupdate = autoupdate; From 4b75b33cf3b0b02a2d676f0678303726a07ff584 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 22 Nov 2024 16:55:13 +0100 Subject: [PATCH 069/114] videoroom: add "threads" parameter to create API --- src/plugins/videoroom-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index e58e9ee..7009d49 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -1257,11 +1257,12 @@ class VideoRoomHandle extends Handle { * @param {boolean} [params.videoorient] - Whether the video-orientation RTP extension must be negotiated * @param {string} [params.h264_profile] - H264 specific profile to prefer * @param {string} [params.vp9_profile] - VP9 specific profile to prefer + * @param {number} [params.threads] - Number of threads to assist with the relaying of publishers in the room * @returns {Promise} */ async create({ room, description, max_publishers, permanent, is_private, secret, pin, admin_key, bitrate, bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, - require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile, vp9_profile }) { + require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile, vp9_profile, threads }) { const body = { request: REQUEST_CREATE, }; @@ -1288,6 +1289,7 @@ class VideoRoomHandle extends Handle { if (typeof videoorient === 'boolean') body.videoorient_ext = videoorient; if (typeof h264_profile === 'string') body.h264_profile = h264_profile; if (typeof vp9_profile === 'string') body.vp9_profile = vp9_profile; + if (typeof threads === 'number') body.threads = threads; const response = await this.message(body); const { event, data: evtdata } = response._janode || {}; From 7e8b920701241dee23f2b68db1ed8300d3a0106f Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 25 Nov 2024 13:22:16 +0100 Subject: [PATCH 070/114] videoroom: add "offer_audio" "offer_video" and "offer_data" to joinSubscriber API --- src/plugins/videoroom-plugin.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 7009d49..b92db4a 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -925,9 +925,12 @@ class VideoRoomHandle extends Handle { * @param {object} params * @param {number|string} params.room - The room to join * @param {number|string} [params.feed=0] - The feed the user wants to subscribe to - * @param {boolean} [params.audio] - True to subscribe to the audio feed - * @param {boolean} [params.video] - True to subscribe to the video feed - * @param {boolean} [params.data] - True to subscribe to the datachannels of the feed + * @param {boolean} [params.audio] - Whether or not audio should be relayed + * @param {boolean} [params.video] - Whether or not video should be relayed + * @param {boolean} [params.data] - Whether or not data should be relayed + * @param {boolean} [params.offer_audio] - Whether or not audio should be negotiated + * @param {boolean} [params.offer_video] - Whether or not video should be negotiated + * @param {boolean} [params.offer_data] - Whether or not data should be negotiated * @param {number} [params.private_id] - The private id to correlate with publisher * @param {number} [params.sc_substream_layer] - Substream layer to receive (0-2), in case simulcasting is enabled * @param {number} [params.sc_substream_fallback_ms] - How much time in ms without receiving packets will make janus drop to the substream below @@ -939,7 +942,7 @@ class VideoRoomHandle extends Handle { * @param {string} [params.pin] - The optional password required to join the room * @returns {Promise} */ - async joinSubscriber({ room, feed, audio, video, data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, streams, autoupdate, use_msid, token, pin }) { + async joinSubscriber({ room, feed, audio, video, data, offer_audio, offer_video, offer_data, private_id, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, streams, autoupdate, use_msid, token, pin }) { const body = { request: REQUEST_JOIN, ptype: PTYPE_LISTENER, @@ -955,6 +958,9 @@ class VideoRoomHandle extends Handle { if (typeof audio === 'boolean') body.audio = audio; if (typeof video === 'boolean') body.video = video; if (typeof data === 'boolean') body.data = data; + if (typeof offer_audio === 'boolean') body.offer_audio = offer_audio; + if (typeof offer_video === 'boolean') body.offer_video = offer_video; + if (typeof offer_data === 'boolean') body.offer_data = offer_data; if (typeof sc_substream_layer === 'number') body.substream = sc_substream_layer; if (typeof sc_substream_fallback_ms === 'number') body.fallback = 1000 * sc_substream_fallback_ms; if (typeof sc_temporal_layers === 'number') body.temporal = sc_temporal_layers; From bb6642ca2d29879d739f729c14bbd0ece9c6b602 Mon Sep 17 00:00:00 2001 From: Sergey Slobodenyuk Date: Mon, 2 Dec 2024 17:06:48 +0500 Subject: [PATCH 071/114] videoroom: fix parse "Leave" and "Unpublish" event (#50) Co-authored-by: Sergey Slobodenyuk --- src/plugins/videoroom-plugin.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index b92db4a..5158af3 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -516,13 +516,6 @@ class VideoRoomHandle extends Handle { janode_event.data.configured = message_data.configured; break; } - /* Display name changed event */ - if (typeof message_data.display !== 'undefined' && typeof message_data.switched === 'undefined') { - janode_event.event = PLUGIN_EVENT.DISPLAY; - janode_event.data.feed = message_data.id; - janode_event.data.display = message_data.display; - break; - } /* Subscribed feed started */ if (typeof message_data.started !== 'undefined') { janode_event.event = PLUGIN_EVENT.STARTED; @@ -559,6 +552,7 @@ class VideoRoomHandle extends Handle { if (typeof message_data.unpublished !== 'undefined') { janode_event.event = PLUGIN_EVENT.UNPUBLISHED; janode_event.data.feed = (message_data.unpublished === 'ok') ? this.feed : message_data.unpublished; + if (message_data.display) janode_event.data.display = message_data.display; break; } /* Leaving confirmation */ @@ -566,6 +560,14 @@ class VideoRoomHandle extends Handle { janode_event.event = PLUGIN_EVENT.LEAVING; janode_event.data.feed = (message_data.leaving === 'ok') ? this.feed : message_data.leaving; if (message_data.reason) janode_event.data.reason = message_data.reason; + if (message_data.display) janode_event.data.display = message_data.display; + break; + } + /* Display name changed event */ + if (typeof message_data.display !== 'undefined' && typeof message_data.switched === 'undefined') { + janode_event.event = PLUGIN_EVENT.DISPLAY; + janode_event.data.feed = message_data.id; + janode_event.data.display = message_data.display; break; } /* Participant kicked out */ From 053a39e61ba94966630d25dda662f74f7e398d11 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 2 Dec 2024 13:09:48 +0100 Subject: [PATCH 072/114] version: bump to v1.7.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24497f9..c63f6e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.7.1", + "version": "1.7.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.7.1", + "version": "1.7.2", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index a263658..0911d0d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.7.1", + "version": "1.7.2", "type": "module", "keywords": [ "janus", From 876099ea80ea34e69ff6e8028536a643efa08461 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 16 Jan 2025 15:18:22 +0100 Subject: [PATCH 073/114] logger: new alias for setLevel. Support a function as parameter. --- src/utils/logger.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/utils/logger.js b/src/utils/logger.js index 7034b23..9818b65 100644 --- a/src/utils/logger.js +++ b/src/utils/logger.js @@ -25,7 +25,12 @@ const printout = (msg_verbosity, console_fn, ...args) => { if (LEVELS_IDX[msg_verbosity] > LEVELS_IDX[log_verbosity]) return; const ts = (new Date()).toISOString(); const prefix = `${ts} - ${msg_verbosity.toUpperCase().padEnd(8, ' ')}:`; - console_fn(prefix, ...args); + if (args.length === 1 && typeof args[0] === 'function') { + const msg = (args[0])(); + console_fn(prefix, msg); + } + else + console_fn(prefix, ...args); }; /** @@ -100,6 +105,7 @@ const Logger = { /* set aliases */ Logger.verb = Logger.verbose; Logger.warn = Logger.warning; +Logger.setLogLevel = Logger.setLevel; Logger.setLevel(log_verbosity); From 1ff1ef94274026438ac4174a76da6712545ce776 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 17 Jan 2025 10:30:55 +0100 Subject: [PATCH 074/114] transport-ws: flag as closed before signaling close event --- src/transport-ws.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transport-ws.js b/src/transport-ws.js index 5e1e7cd..9d1148a 100644 --- a/src/transport-ws.js +++ b/src/transport-ws.js @@ -146,9 +146,9 @@ class TransportWs { /* Start cleanup */ /* Cancel the KA task */ this._unsetPingTask(); + this._closed = true; this._connection._signalClose(this._closing); this._closing = false; - this._closed = true; /* removeAllListeners is only supported on the node ws module */ if (typeof this._ws.removeAllListeners === 'function') this._ws.removeAllListeners(); }, { once: true }); From 8609807e56fd919868eac279df70ec13fab87b90 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Fri, 17 Jan 2025 10:45:40 +0100 Subject: [PATCH 075/114] transport-ws: set closing to false before signaling close event --- src/transport-ws.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/transport-ws.js b/src/transport-ws.js index 9d1148a..0f34a3e 100644 --- a/src/transport-ws.js +++ b/src/transport-ws.js @@ -146,9 +146,10 @@ class TransportWs { /* Start cleanup */ /* Cancel the KA task */ this._unsetPingTask(); - this._closed = true; - this._connection._signalClose(this._closing); + const wasClosing = this._closing; this._closing = false; + this._closed = true; + this._connection._signalClose(wasClosing); /* removeAllListeners is only supported on the node ws module */ if (typeof this._ws.removeAllListeners === 'function') this._ws.removeAllListeners(); }, { once: true }); From 239dfa02602ab92cec036e04cf90268f9329054d Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 20 Jan 2025 18:22:51 +0100 Subject: [PATCH 076/114] deps: update --- examples/audiobridge/package-lock.json | 554 +++++++++++++++--------- examples/echotest/package-lock.json | 554 +++++++++++++++--------- examples/streaming/package-lock.json | 554 +++++++++++++++--------- examples/videoroom-ms/package-lock.json | 554 +++++++++++++++--------- examples/videoroom/package-lock.json | 554 +++++++++++++++--------- package-lock.json | 504 +++++++++++---------- 6 files changed, 2063 insertions(+), 1211 deletions(-) diff --git a/examples/audiobridge/package-lock.json b/examples/audiobridge/package-lock.json index 835af6a..a7e0ca7 100644 --- a/examples/audiobridge/package-lock.json +++ b/examples/audiobridge/package-lock.json @@ -14,33 +14,38 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" }, "node_modules/@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "22.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", + "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -52,20 +57,23 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -75,7 +83,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -89,20 +97,32 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -115,6 +135,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -126,14 +147,16 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -141,12 +164,14 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -159,30 +184,16 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -191,66 +202,87 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", - "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", "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", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -262,17 +294,16 @@ } }, "node_modules/engine.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -281,6 +312,19 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { "node": ">= 0.4" } @@ -288,47 +332,50 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -337,15 +384,20 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -360,6 +412,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -368,6 +421,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -376,20 +430,27 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -398,32 +459,24 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { + "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -432,9 +485,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -446,6 +500,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -457,6 +512,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -472,6 +528,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -482,33 +539,50 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -517,6 +591,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -528,6 +603,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -536,6 +612,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -546,12 +623,14 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -560,14 +639,19 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -576,6 +660,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -587,19 +672,22 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -609,11 +697,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -626,6 +715,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -634,6 +724,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -661,17 +752,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -691,55 +785,106 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -749,15 +894,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -766,20 +912,22 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", - "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", "dependencies": { "debug": "~4.3.4", - "ws": "~8.11.0" + "ws": "~8.17.1" } }, "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -791,14 +939,16 @@ } }, "node_modules/socket.io-adapter/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -808,11 +958,12 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -824,16 +975,18 @@ } }, "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -845,14 +998,16 @@ } }, "node_modules/socket.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -861,6 +1016,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -869,6 +1025,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -878,14 +1035,16 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -894,6 +1053,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -902,20 +1062,22 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/examples/echotest/package-lock.json b/examples/echotest/package-lock.json index bf94428..9882b6b 100644 --- a/examples/echotest/package-lock.json +++ b/examples/echotest/package-lock.json @@ -14,33 +14,38 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" }, "node_modules/@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "22.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", + "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -52,20 +57,23 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -75,7 +83,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -89,20 +97,32 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -115,6 +135,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -126,14 +147,16 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -141,12 +164,14 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -159,30 +184,16 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -191,66 +202,87 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", - "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", "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", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -262,17 +294,16 @@ } }, "node_modules/engine.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -281,6 +312,19 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { "node": ">= 0.4" } @@ -288,47 +332,50 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -337,15 +384,20 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -360,6 +412,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -368,6 +421,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -376,20 +430,27 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -398,32 +459,24 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { + "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -432,9 +485,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -446,6 +500,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -457,6 +512,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -472,6 +528,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -482,33 +539,50 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -517,6 +591,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -528,6 +603,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -536,6 +612,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -546,12 +623,14 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -560,14 +639,19 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -576,6 +660,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -587,19 +672,22 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -609,11 +697,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -626,6 +715,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -634,6 +724,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -661,17 +752,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -691,55 +785,106 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -749,15 +894,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -766,20 +912,22 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", - "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", "dependencies": { "debug": "~4.3.4", - "ws": "~8.11.0" + "ws": "~8.17.1" } }, "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -791,14 +939,16 @@ } }, "node_modules/socket.io-adapter/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -808,11 +958,12 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -824,16 +975,18 @@ } }, "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -845,14 +998,16 @@ } }, "node_modules/socket.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -861,6 +1016,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -869,6 +1025,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -878,14 +1035,16 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -894,6 +1053,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -902,20 +1062,22 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/examples/streaming/package-lock.json b/examples/streaming/package-lock.json index 356288b..a447187 100644 --- a/examples/streaming/package-lock.json +++ b/examples/streaming/package-lock.json @@ -14,33 +14,38 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" }, "node_modules/@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "22.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", + "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -52,20 +57,23 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -75,7 +83,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -89,20 +97,32 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -115,6 +135,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -126,14 +147,16 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -141,12 +164,14 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -159,30 +184,16 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -191,66 +202,87 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", - "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", "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", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -262,17 +294,16 @@ } }, "node_modules/engine.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -281,6 +312,19 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { "node": ">= 0.4" } @@ -288,47 +332,50 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -337,15 +384,20 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -360,6 +412,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -368,6 +421,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -376,20 +430,27 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -398,32 +459,24 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { + "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -432,9 +485,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -446,6 +500,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -457,6 +512,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -472,6 +528,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -482,33 +539,50 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -517,6 +591,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -528,6 +603,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -536,6 +612,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -546,12 +623,14 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -560,14 +639,19 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -576,6 +660,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -587,19 +672,22 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -609,11 +697,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -626,6 +715,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -634,6 +724,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -661,17 +752,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -691,55 +785,106 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -749,15 +894,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -766,20 +912,22 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", - "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", "dependencies": { "debug": "~4.3.4", - "ws": "~8.11.0" + "ws": "~8.17.1" } }, "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -791,14 +939,16 @@ } }, "node_modules/socket.io-adapter/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -808,11 +958,12 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -824,16 +975,18 @@ } }, "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -845,14 +998,16 @@ } }, "node_modules/socket.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -861,6 +1016,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -869,6 +1025,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -878,14 +1035,16 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -894,6 +1053,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -902,20 +1062,22 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/examples/videoroom-ms/package-lock.json b/examples/videoroom-ms/package-lock.json index e42c5ef..534a8ae 100644 --- a/examples/videoroom-ms/package-lock.json +++ b/examples/videoroom-ms/package-lock.json @@ -14,33 +14,38 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" }, "node_modules/@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "22.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", + "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -52,20 +57,23 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -75,7 +83,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -89,20 +97,32 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -115,6 +135,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -126,14 +147,16 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -141,12 +164,14 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -159,30 +184,16 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -191,66 +202,87 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", - "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", "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", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -262,17 +294,16 @@ } }, "node_modules/engine.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -281,6 +312,19 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { "node": ">= 0.4" } @@ -288,47 +332,50 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -337,15 +384,20 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -360,6 +412,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -368,6 +421,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -376,20 +430,27 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -398,32 +459,24 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { + "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -432,9 +485,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -446,6 +500,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -457,6 +512,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -472,6 +528,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -482,33 +539,50 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -517,6 +591,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -528,6 +603,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -536,6 +612,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -546,12 +623,14 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -560,14 +639,19 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -576,6 +660,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -587,19 +672,22 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -609,11 +697,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -626,6 +715,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -634,6 +724,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -661,17 +752,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -691,55 +785,106 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -749,15 +894,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -766,20 +912,22 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", - "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", "dependencies": { "debug": "~4.3.4", - "ws": "~8.11.0" + "ws": "~8.17.1" } }, "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -791,14 +939,16 @@ } }, "node_modules/socket.io-adapter/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -808,11 +958,12 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -824,16 +975,18 @@ } }, "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -845,14 +998,16 @@ } }, "node_modules/socket.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -861,6 +1016,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -869,6 +1025,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -878,14 +1035,16 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -894,6 +1053,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -902,20 +1062,22 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/examples/videoroom/package-lock.json b/examples/videoroom/package-lock.json index 58d833e..c50b185 100644 --- a/examples/videoroom/package-lock.json +++ b/examples/videoroom/package-lock.json @@ -14,33 +14,38 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" }, "node_modules/@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "22.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", + "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -52,20 +57,23 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -75,7 +83,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -89,20 +97,32 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -115,6 +135,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -126,14 +147,16 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -141,12 +164,14 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -159,30 +184,16 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -191,66 +202,87 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", - "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", "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", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -262,17 +294,16 @@ } }, "node_modules/engine.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -281,6 +312,19 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { "node": ">= 0.4" } @@ -288,47 +332,50 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -337,15 +384,20 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -360,6 +412,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -368,6 +421,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -376,20 +430,27 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -398,32 +459,24 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { + "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -432,9 +485,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -446,6 +500,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -457,6 +512,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -472,6 +528,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -482,33 +539,50 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -517,6 +591,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -528,6 +603,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -536,6 +612,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -546,12 +623,14 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -560,14 +639,19 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -576,6 +660,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -587,19 +672,22 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -609,11 +697,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -626,6 +715,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -634,6 +724,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -661,17 +752,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -691,55 +785,106 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -749,15 +894,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -766,20 +912,22 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", - "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", "dependencies": { "debug": "~4.3.4", - "ws": "~8.11.0" + "ws": "~8.17.1" } }, "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -791,14 +939,16 @@ } }, "node_modules/socket.io-adapter/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -808,11 +958,12 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -824,16 +975,18 @@ } }, "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -845,14 +998,16 @@ } }, "node_modules/socket.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -861,6 +1016,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -869,6 +1025,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -878,14 +1035,16 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -894,6 +1053,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -902,20 +1062,22 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/package-lock.json b/package-lock.json index c63f6e6..93905a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,16 +23,20 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } @@ -42,6 +46,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -50,33 +55,49 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.15.1.tgz", - "integrity": "sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.3", + "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", - "minimatch": "^3.0.5" + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -100,6 +121,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -108,28 +130,83 @@ } }, "node_modules/@eslint/js": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", - "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", + "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.10.0", + "levn": "^0.4.1" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -139,10 +216,11 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -151,46 +229,26 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, - "engines": { - "node": ">= 8" - } + "license": "MIT" }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } + "license": "MIT" }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -203,6 +261,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -212,6 +271,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -223,20 +283,12 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -251,18 +303,21 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", "dependencies": { "file-uri-to-path": "1.0.0" } @@ -272,6 +327,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -282,6 +338,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -291,6 +348,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -307,6 +365,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -318,19 +377,22 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -341,12 +403,13 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -361,13 +424,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -376,28 +441,33 @@ } }, "node_modules/eslint": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.4.0.tgz", - "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", + "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/config-array": "^0.15.1", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.4.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.10.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.18.0", + "@eslint/plugin-kit": "^0.2.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -406,15 +476,11 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -423,14 +489,23 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -443,10 +518,11 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -455,14 +531,15 @@ } }, "node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -472,10 +549,11 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -488,6 +566,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -500,6 +579,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -509,6 +589,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -517,34 +598,29 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } + "license": "MIT" }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -555,13 +631,15 @@ "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -578,6 +656,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -587,16 +666,18 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, + "license": "ISC" }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -605,10 +686,11 @@ } }, "node_modules/globals": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.4.0.tgz", - "integrity": "sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==", + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", + "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -621,15 +703,17 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -639,6 +723,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -655,6 +740,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -664,6 +750,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -673,6 +760,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -680,25 +768,18 @@ "node": ">=0.10.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", "peerDependencies": { "ws": "*" } @@ -708,6 +789,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -719,25 +801,29 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -747,6 +833,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -760,6 +847,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -774,13 +862,15 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -789,27 +879,31 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/nan": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", - "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==" + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -827,6 +921,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -842,6 +937,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -857,6 +953,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -869,6 +966,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -878,6 +976,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -887,6 +986,7 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -896,77 +996,27 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -979,18 +1029,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "license": "MIT", "engines": { "node": ">=8" } @@ -1000,6 +1039,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -1012,6 +1052,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -1019,17 +1060,12 @@ "node": ">=8" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -1042,6 +1078,7 @@ "resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.6.tgz", "integrity": "sha512-AURroAsb73BZ6CdAyMrTk/hYKNj3DuYYEuOaB8bYMOHGKupRNScw90Q5C71tWJc3uE7dIeXRyuwN0xLLq3vDTg==", "hasInstallScript": true, + "license": "ISC", "dependencies": { "bindings": "^1.5.0", "nan": "^2.16.0" @@ -1055,6 +1092,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -1064,6 +1102,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -1079,14 +1118,16 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -1108,6 +1149,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, From efc666a95f98e539846547e17232b9a19ff1623d Mon Sep 17 00:00:00 2001 From: Samuele Date: Wed, 26 Feb 2025 11:11:35 +0100 Subject: [PATCH 077/114] streaming: enhanced multistream support (#52) --- src/plugins/streaming-plugin.js | 108 ++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 39 deletions(-) diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index acc1230..2258dce 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -425,18 +425,25 @@ class StreamingHandle extends Handle { * @param {string} [params.audio] - The filename for audio * @param {string} [params.video] - The filename for video * @param {string} [params.data] - The filename for data + * @param {object[]} [params.media] - [multistream] The media object, each media includes mid, filename * @param {string} [params.secret] * @returns {Promise} */ - async startRecording({ id, audio, video, data, secret }) { + async startRecording({ id, audio, video, data, media, secret }) { const body = { request: REQUEST_RECORDING, action: ACTION_START_REC, id, }; - if (audio) body.audio = audio; - if (video) body.video = video; - if (data) body.data = data; + /* [multistream] */ + if (media && Array.isArray(media)) { + body.media = media; + } + else { + if (audio) body.audio = audio; + if (video) body.video = video; + if (data) body.data = data; + } if (typeof secret === 'string') body.secret = '' + secret; const response = await this.message(body); @@ -455,18 +462,25 @@ class StreamingHandle extends Handle { * @param {boolean} [params.audio=true] - True to stop recording of audio * @param {boolean} [params.video=true] - True to stop recording of video * @param {boolean} [params.data=true] - True to stop recording of data + * @param {object[]} [params.media] - [multistream] The media object, each media includes mid * @param {string} [params.secret] * @returns {Promise} */ - async stopRecording({ id, audio = true, video = true, data = true, secret }) { + async stopRecording({ id, audio = true, video = true, data = true, media, secret }) { const body = { request: REQUEST_RECORDING, action: ACTION_STOP_REC, id, - audio, - video, - data, }; + /* [multistream] */ + if (media && Array.isArray(media)) { + body.media = media; + } + else { + body.audio = audio; + body.video = video; + body.data = data; + } if (typeof secret === 'string') body.secret = '' + secret; const response = await this.message(body); @@ -558,12 +572,13 @@ class StreamingHandle extends Handle { * @param {object} [params.data] - The datachannel descriptor for the mp * @param {number} [params.data.port] - Port used for datachannels packets * @param {boolean} [params.data.buffer] - Enable buffering of the datachannels + * @param {object[]} [params.media] - [multistream] The media object, each media includes type, mid, port, pt ... * @param {number} [params.threads] - The number of helper threads used in this mp * @param {object} [params.metadata] - An opaque metadata to add to the mp * @param {number} [params.collision] - The stream collision discarding time in number of milliseconds (0=disabled) * @returns {Promise} */ - async createRtpMountpoint({ id = 0, name, description, secret, pin, admin_key, permanent = false, is_private = false, e2ee = false, audio, video, data, threads, metadata, collision }) { + async createRtpMountpoint({ id = 0, name, description, secret, pin, admin_key, permanent = false, is_private = false, e2ee = false, audio, video, data, media, threads, metadata, collision }) { const body = { request: REQUEST_CREATE, type: 'rtp', @@ -571,9 +586,6 @@ class StreamingHandle extends Handle { permanent, is_private, e2ee, - audio: false, - video: false, - data: false, collision: 2000, }; if (typeof name === 'string') body.name = name; @@ -581,35 +593,44 @@ class StreamingHandle extends Handle { if (typeof secret === 'string') body.secret = secret; if (typeof pin === 'string') body.pin = pin; if (typeof admin_key === 'string') body.admin_key = admin_key; - if (typeof audio === 'object' && audio) { - body.audio = true; - body.audioport = (typeof audio.port === 'number') ? audio.port : 0; - if (typeof audio.rtcpport === 'number') body.audiortcpport = audio.rtcppport; - if (typeof audio.mcast === 'string') body.audiomcast = audio.mcast; - if (audio.pt) body.audiopt = audio.pt; - if (audio.rtpmap) body.audiortpmap = audio.rtpmap; - if (typeof audio.skew === 'boolean') body.audioskew = audio.skew; + /* [multistream] */ + if (media && Array.isArray(media)) { + body.media = media; } - if (typeof video === 'object' && video) { - body.video = true; - body.videoport = (typeof video.port === 'number') ? video.port : 0; - if (typeof video.rtcpport === 'number') body.videortcpport = video.rtcpport; - if (typeof video.mcast === 'string') body.videomcast = video.mcast; - if (video.pt) body.videopt = video.pt; - if (video.rtpmap) body.videortpmap = video.rtpmap; - if (video.fmtp) body.videofmtp = video.fmtp; - if (typeof video.buffer === 'boolean') body.videobufferkf = video.buffer; - if (typeof video.skew === 'boolean') body.videoskew = video.skew; - if (typeof video.port2 === 'number' && typeof video.port3 === 'number') { - body.videosimulcast = true; - body.videoport2 = video.port2; - body.videoport3 = video.port3; + else { + body.audio = false; + body.video = false; + body.data = false; + if (typeof audio === 'object' && audio) { + body.audio = true; + body.audioport = (typeof audio.port === 'number') ? audio.port : 0; + if (typeof audio.rtcpport === 'number') body.audiortcpport = audio.rtcppport; + if (typeof audio.mcast === 'string') body.audiomcast = audio.mcast; + if (audio.pt) body.audiopt = audio.pt; + if (audio.rtpmap) body.audiortpmap = audio.rtpmap; + if (typeof audio.skew === 'boolean') body.audioskew = audio.skew; + } + if (typeof video === 'object' && video) { + body.video = true; + body.videoport = (typeof video.port === 'number') ? video.port : 0; + if (typeof video.rtcpport === 'number') body.videortcpport = video.rtcpport; + if (typeof video.mcast === 'string') body.videomcast = video.mcast; + if (video.pt) body.videopt = video.pt; + if (video.rtpmap) body.videortpmap = video.rtpmap; + if (video.fmtp) body.videofmtp = video.fmtp; + if (typeof video.buffer === 'boolean') body.videobufferkf = video.buffer; + if (typeof video.skew === 'boolean') body.videoskew = video.skew; + if (typeof video.port2 === 'number' && typeof video.port3 === 'number') { + body.videosimulcast = true; + body.videoport2 = video.port2; + body.videoport3 = video.port3; + } + } + if (typeof data === 'object' && data) { + body.data = true; + body.dataport = (typeof data.port === 'number') ? data.port : 0; + if (typeof data.buffer === 'boolean') body.databuffermsg = data.buffer; } - } - if (typeof data === 'object' && data) { - body.data = true; - body.dataport = (typeof data.port === 'number') ? data.port : 0; - if (typeof data.buffer === 'boolean') body.databuffermsg = data.buffer; } if (typeof threads === 'number' && threads > 0) body.threads = threads; if (metadata) body.metadata = metadata; @@ -691,6 +712,15 @@ class StreamingHandle extends Handle { * @property {number} [video_port_3] - The port for RTP video (simulcast) * @property {number} [video_rtcp_port] - The port for RTCP video * @property {number} [data_port] - The port for datachannels + * @property {object[]} [ports] - [multistream] The ports used by the RTP mountpoint + * @property {string} ports.type - The type of the port (audio, video, data) + * @property {string} ports.mid - The unique mid of the stream + * @property {string} [ports.msid] - The msid of the stream + * @property {string} [ports.host] - The address in use for this stream + * @property {number} [ports.port] - The port on which the plugin listens for this stream's media + * @property {number} [ports.rtcp_port] - The local port for receiving and sending RTCP feedback + * @property {number} [ports.port_2] - The second local port for receiving video frames (only for RTP video, and simulcasting) + * @property {number} [ports.port_3] - The third local port for receiving video frames (only for RTP video, and simulcasting) */ /** From ed70b3e4907d3971572e6d667e546c0b81e079ef Mon Sep 17 00:00:00 2001 From: Samuele Date: Wed, 26 Feb 2025 17:29:03 +0100 Subject: [PATCH 078/114] videoroom: add "notify_joining" parameter to create API (#53) --- src/plugins/videoroom-plugin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 5158af3..f9b4556 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -1259,6 +1259,7 @@ class VideoRoomHandle extends Handle { * @param {number} [params.talking_level_threshold] - Audio level threshold for talking events in the range [0, 127] * @param {number} [params.talking_packets_threshold] - Audio packets threshold for talking events * @param {boolean} [params.require_pvtid] - Whether subscriptions are required to provide a valid private_id + * @param {boolean} [params.notify_joining] - Whether to notify all participants when a new participant joins the room * @param {boolean} [params.require_e2ee] - Whether all participants are required to publish and subscribe using e2e encryption * @param {boolean} [params.record] - Wheter to enable recording of any publisher * @param {string} [params.rec_dir] - Folder where recordings should be stored @@ -1270,7 +1271,7 @@ class VideoRoomHandle extends Handle { */ async create({ room, description, max_publishers, permanent, is_private, secret, pin, admin_key, bitrate, bitrate_cap, fir_freq, audiocodec, videocodec, talking_events, talking_level_threshold, talking_packets_threshold, - require_pvtid, require_e2ee, record, rec_dir, videoorient, h264_profile, vp9_profile, threads }) { + require_pvtid, notify_joining, require_e2ee, record, rec_dir, videoorient, h264_profile, vp9_profile, threads }) { const body = { request: REQUEST_CREATE, }; @@ -1291,6 +1292,7 @@ class VideoRoomHandle extends Handle { if (typeof talking_level_threshold === 'number' && talking_level_threshold >= 0 && talking_level_threshold <= 127) body.audio_level_average = talking_level_threshold; if (typeof talking_packets_threshold === 'number' && talking_packets_threshold > 0) body.audio_active_packets = talking_packets_threshold; if (typeof require_pvtid === 'boolean') body.require_pvtid = require_pvtid; + if (typeof notify_joining === 'boolean') body.notify_joining = notify_joining; if (typeof require_e2ee === 'boolean') body.require_e2ee = require_e2ee; if (typeof record === 'boolean') body.record = record; if (typeof rec_dir === 'string') body.rec_dir = rec_dir; From 3e603b6bf16dd00e35017bcdbeb2b7e996989ae6 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 2 Apr 2025 12:07:26 +0200 Subject: [PATCH 079/114] audiobridge: add "rtp_participant" to configure API --- src/plugins/audiobridge-plugin.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index c610364..d9b365b 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -460,10 +460,11 @@ class AudioBridgeHandle extends Handle { * @param {number} [params.expected_loss] - Set a new expected_loss value for this participant (overrides room default) * @param {number} [params.prebuffer] - Set a new prebuffer value (overrides room default) * @param {string} [params.group] - Set the group that the participant belongs to - * @param {RTCSessionDescription} [params.jsep=null] - JSEP offer + * @param {module:audiobridge-plugin~RtpParticipant} [params.rtp_participant] - Set a descriptor object if you need a RTP participant + * @param {RTCSessionDescription} [params.jsep=null] - JSEP offer/answer to be sent to Janus * @returns {Promise} */ - async configure({ display, muted, quality, bitrate, volume, record, filename, expected_loss, prebuffer, group, jsep = null }) { + async configure({ display, muted, quality, bitrate, volume, record, filename, expected_loss, prebuffer, group, rtp_participant, jsep = null }) { const body = { request: REQUEST_CONFIGURE, }; @@ -477,6 +478,7 @@ class AudioBridgeHandle extends Handle { if (typeof expected_loss === 'number') body.expected_loss = expected_loss; if (typeof prebuffer === 'number') body.prebuffer = prebuffer; if (typeof group === 'string') body.group = group; + if (typeof rtp_participant === 'object' && rtp_participant) body.rtp = rtp_participant; const response = await this.message(body, jsep); const { event, data: evtdata } = response._janode || {}; @@ -493,6 +495,7 @@ class AudioBridgeHandle extends Handle { if (typeof body.filename !== 'undefined') evtdata.filename = body.filename; if (typeof body.prebuffer !== 'undefined') evtdata.prebuffer = body.prebuffer; if (typeof body.group !== 'undefined') evtdata.group = body.group; + if (typeof body.rtp !== 'undefined') evtdata.rtp_participant = body.rtp; return evtdata; } const error = new Error(`unexpected response to ${body.request} request`); From de30d416ef911093095d5a9f8a026e91db1a73d2 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Thu, 3 Apr 2025 16:11:57 +0200 Subject: [PATCH 080/114] handle: use core helpers for setting and getting plugin events --- src/handle.js | 38 +++++++++++++++++++ src/plugins/audiobridge-plugin.js | 57 ++++++++++++----------------- src/plugins/echotest-plugin.js | 17 ++------- src/plugins/streaming-plugin.js | 44 ++++++++-------------- src/plugins/videoroom-plugin.js | 61 +++++++++++++------------------ 5 files changed, 105 insertions(+), 112 deletions(-) diff --git a/src/handle.js b/src/handle.js index 80c6578..f6aaef7 100644 --- a/src/handle.js +++ b/src/handle.js @@ -13,6 +13,7 @@ const LOG_NS = '[handle.js]'; import { getNumericID } from './utils/utils.js'; import { JANUS, JANODE, isAckData, isResponseData, isErrorData } from './protocol.js'; +const PLUGIN_EVENT_SYM = Symbol('plugin_event'); /** * Class representing a Janode handle.
* @@ -387,6 +388,43 @@ class Handle extends EventEmitter { request.handle_id = request.handle_id || this.id; } + /** + * Helper method used by plugins to create a new plugin event and assign it to a janus message. + * + * @private + * @param {object} janus_message + * @returns {object} + */ + _newPluginEvent(janus_message) { + /* Prepare an object for the output Janode event */ + const janode_event = { + /* The name of the resolved event */ + event: null, + /* The event payload */ + data: {}, + }; + + /* Add JSEP data if available */ + if (janus_message.jsep) { + janode_event.data.jsep = janus_message.jsep; + if (typeof janus_message.jsep.e2ee === 'boolean') janode_event.data.e2ee = janus_message.jsep.e2ee; + } + + janus_message[PLUGIN_EVENT_SYM] = janode_event; + return janode_event; + } + + /** + * Helper method used by plugins to get an assigned plugin eventfrom a handled janus message. + * + * @private + * @param {object} janus_message + * @returns {object} + */ + _getPluginEvent(janus_message) { + return janus_message[PLUGIN_EVENT_SYM] || {}; + } + /** * Stub handleMessage (it is overriden by specific plugin handlers). * Implementations must return falsy values for unhandled events and truthy value diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index c610364..035e320 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -107,7 +107,7 @@ class AudioBridgeHandle extends Handle { * @returns {object} A falsy value for unhandled events, a truthy value for handled events */ handleMessage(janus_message) { - const { plugindata, jsep, transaction } = janus_message; + const { plugindata, transaction } = janus_message; if (plugindata && plugindata.data && plugindata.data.audiobridge) { /** * @type {AudioBridgeData} @@ -116,15 +116,7 @@ class AudioBridgeHandle extends Handle { const { audiobridge, error, error_code, room } = message_data; /* Prepare an object for the output Janode event */ - const janode_event = { - /* The name of the resolved event */ - event: null, - /* The event payload */ - data: {}, - }; - - /* Add JSEP data if available */ - if (jsep) janode_event.data.jsep = jsep; + const janode_event = this._newPluginEvent(janus_message); /* Add room information if available */ if (room) janode_event.data.room = room; @@ -132,9 +124,6 @@ class AudioBridgeHandle extends Handle { /* That means that a transaction has already been closed or this is an async event */ const emit = (this.ownsTransaction(transaction) === false); - /* Use the "janode" property to store the output event */ - janus_message._janode = janode_event; - switch (audiobridge) { /* success response */ @@ -439,7 +428,7 @@ class AudioBridgeHandle extends Handle { if (typeof codec === 'string') body.codec = codec; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.JOINED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -479,7 +468,7 @@ class AudioBridgeHandle extends Handle { if (typeof group === 'string') body.group = group; const response = await this.message(body, jsep); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.CONFIGURED) { /* Janus does not reply with configured data, so we need to re-use the requested configuration */ /* Use feed and room from handle status */ @@ -511,7 +500,7 @@ class AudioBridgeHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.AUDIO_HANGINGUP) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -529,7 +518,7 @@ class AudioBridgeHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.LEAVING) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -558,7 +547,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.PARTICIPANTS_LIST) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -583,7 +572,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) { /* Add data missing from Janus response */ evtdata.room = body.room; @@ -608,7 +597,7 @@ class AudioBridgeHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.EXISTS) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -626,7 +615,7 @@ class AudioBridgeHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.ROOMS_LIST) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -686,7 +675,7 @@ class AudioBridgeHandle extends Handle { if (typeof denoise === 'boolean') body.denoise = denoise; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.CREATED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -711,7 +700,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.DESTROYED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -740,7 +729,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.RECORDING) { evtdata.room = body.room; return evtdata; @@ -769,7 +758,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -810,7 +799,7 @@ class AudioBridgeHandle extends Handle { if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.RTP_FWD) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -837,7 +826,7 @@ class AudioBridgeHandle extends Handle { if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.RTP_FWD) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -862,7 +851,7 @@ class AudioBridgeHandle extends Handle { if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.FWD_LIST) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -887,7 +876,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) { /* Add data missing from Janus response */ evtdata.room = body.room; @@ -916,7 +905,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) { /* Add data missing from Janus response */ evtdata.room = body.room; @@ -943,7 +932,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) { evtdata.room = body.room; return evtdata; @@ -968,7 +957,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) { evtdata.room = body.room; return evtdata; @@ -999,7 +988,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) { evtdata.feed = feed; return evtdata; @@ -1030,7 +1019,7 @@ class AudioBridgeHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) { evtdata.feed = feed; return evtdata; diff --git a/src/plugins/echotest-plugin.js b/src/plugins/echotest-plugin.js index cfe4b94..f67246c 100644 --- a/src/plugins/echotest-plugin.js +++ b/src/plugins/echotest-plugin.js @@ -46,7 +46,7 @@ class EchoTestHandle extends Handle { * @returns {object} A falsy value for unhandled events, a truthy value for handled events */ handleMessage(janus_message) { - const { plugindata, jsep, transaction } = janus_message; + const { plugindata, transaction } = janus_message; if (plugindata && plugindata.data && plugindata.data.echotest) { /** * @type {EchoTestData} @@ -55,23 +55,12 @@ class EchoTestHandle extends Handle { const { echotest, event, error, error_code, result } = message_data; /* Prepare an object for the output Janode event */ - const janode_event = { - /* The name of the resolved event */ - event: null, - /* The event payload */ - data: {}, - }; - - /* Add JSEP data if available */ - if (jsep) janode_event.data.jsep = jsep; + const janode_event = this._newPluginEvent(janus_message); /* The plugin will emit an event only if the handle does not own the transaction */ /* That means that a transaction has already been closed or this is an async event */ const emit = (this.ownsTransaction(transaction) === false); - /* Use the "janode" property to store the output event */ - janus_message._janode = janode_event; - switch (echotest) { /* Generic event (e.g. result, error) */ @@ -141,7 +130,7 @@ class EchoTestHandle extends Handle { if (typeof filename === 'string') body.filename = filename; const response = await this.message(body, jsep); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.RESULT && evtdata.result === 'ok') return evtdata; const error = new Error('invalid echotest result'); diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index 2258dce..ac3b231 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -76,7 +76,7 @@ class StreamingHandle extends Handle { * @returns {object} A falsy value for unhandled events, a truthy value for handled events */ handleMessage(janus_message) { - const { plugindata, jsep, transaction } = janus_message; + const { plugindata, transaction } = janus_message; if (plugindata && plugindata.data && plugindata.data.streaming) { /** * @type {StreamingData} @@ -85,24 +85,12 @@ class StreamingHandle extends Handle { const { streaming, error, error_code } = message_data; /* Prepare an object for the output Janode event */ - const janode_event = { - /* The name of the resolved event */ - event: null, - /* The event payload */ - data: {}, - }; - - /* Add JSEP data if available */ - if (jsep) janode_event.data.jsep = jsep; - if (jsep && typeof jsep.e2ee === 'boolean') janode_event.data.e2ee = jsep.e2ee; + const janode_event = this._newPluginEvent(janus_message); /* The plugin will emit an event only if the handle does not own the transaction */ /* That means that a transaction has already been closed or this is an async event */ const emit = (this.ownsTransaction(transaction) === false); - /* Use the "janode" property to store the output event */ - janus_message._janode = janode_event; - switch (streaming) { /* Ok is a success response */ @@ -235,7 +223,7 @@ class StreamingHandle extends Handle { if (typeof restart === 'boolean') body.restart = restart; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response);; if (event === PLUGIN_EVENT.STATUS && (evtdata.status === 'preparing' || evtdata.status === 'updating')) { /* Set current mp to subscribed id */ this.mp = id; @@ -265,7 +253,7 @@ class StreamingHandle extends Handle { jsep.e2ee = (typeof e2ee === 'boolean') ? e2ee : jsep.e2ee; const response = await this.message(body, jsep); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response);; if (event === PLUGIN_EVENT.STATUS && (evtdata.status === 'starting' || evtdata.status === 'started')) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -283,7 +271,7 @@ class StreamingHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response);; if (event === PLUGIN_EVENT.STATUS && evtdata.status === 'pausing') return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -301,7 +289,7 @@ class StreamingHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response);; if (event === PLUGIN_EVENT.STATUS && evtdata.status === 'stopping') return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -322,7 +310,7 @@ class StreamingHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response);; if (event === PLUGIN_EVENT.SWITCHED && evtdata.switched === 'ok') { /* Set current mp to the switched id */ this.mp = evtdata.id; @@ -360,7 +348,7 @@ class StreamingHandle extends Handle { if (typeof temporal_layer === 'number') body.temporal_layer = temporal_layer; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.CONFIGURED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -387,7 +375,7 @@ class StreamingHandle extends Handle { if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.LIST) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -410,7 +398,7 @@ class StreamingHandle extends Handle { if (typeof secret === 'string') body.secret = '' + secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.INFO) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -447,7 +435,7 @@ class StreamingHandle extends Handle { if (typeof secret === 'string') body.secret = '' + secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.OK) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -484,7 +472,7 @@ class StreamingHandle extends Handle { if (typeof secret === 'string') body.secret = '' + secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.OK) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -507,7 +495,7 @@ class StreamingHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.OK) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -532,7 +520,7 @@ class StreamingHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.OK) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -637,7 +625,7 @@ class StreamingHandle extends Handle { if (typeof collision === 'number') body.collision = collision; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.CREATED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -662,7 +650,7 @@ class StreamingHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.DESTROYED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index f9b4556..f6956cc 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -122,7 +122,7 @@ class VideoRoomHandle extends Handle { * @returns {object} A falsy value for unhandled events, a truthy value for handled events */ handleMessage(janus_message) { - const { plugindata, jsep, transaction } = janus_message; + const { plugindata, transaction } = janus_message; if (plugindata && plugindata.data && plugindata.data.videoroom) { /** * @type {VideoRoomData} @@ -131,16 +131,8 @@ class VideoRoomHandle extends Handle { const { videoroom, error, error_code, room } = message_data; /* Prepare an object for the output Janode event */ - const janode_event = { - /* The name of the resolved event */ - event: null, - /* The event payload */ - data: {}, - }; - - /* Add JSEP data if available */ - if (jsep) janode_event.data.jsep = jsep; - if (jsep && typeof jsep.e2ee === 'boolean') janode_event.data.e2ee = jsep.e2ee; + const janode_event = this._newPluginEvent(janus_message); + /* Add room information if available */ if (room) janode_event.data.room = room; @@ -148,9 +140,6 @@ class VideoRoomHandle extends Handle { /* That means that a transaction has already been closed or this is an async event */ const emit = (this.ownsTransaction(transaction) === false); - /* Use the "janode" property to store the output event */ - janus_message._janode = janode_event; - switch (videoroom) { /* Success response */ @@ -661,7 +650,7 @@ class VideoRoomHandle extends Handle { if (descriptions && Array.isArray(descriptions)) body.descriptions = descriptions; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.PUB_JOINED) { if (body.display) evtdata.display = body.display; return evtdata; @@ -732,7 +721,7 @@ class VideoRoomHandle extends Handle { throw e; }); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.PUB_JOINED) { if (body.display) evtdata.display = body.display; return evtdata; @@ -821,7 +810,7 @@ class VideoRoomHandle extends Handle { throw e; }); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.CONFIGURED && evtdata.configured === 'ok') { if (body.display) evtdata.display = body.display; if (typeof body.request === 'boolean') evtdata.restart = body.restart; @@ -894,7 +883,7 @@ class VideoRoomHandle extends Handle { throw e; }); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.CONFIGURED && evtdata.configured === 'ok') { if (body.display) evtdata.display = body.display; return evtdata; @@ -914,7 +903,7 @@ class VideoRoomHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.UNPUBLISHED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -976,7 +965,7 @@ class VideoRoomHandle extends Handle { if (typeof use_msid === 'boolean') body.use_msid = use_msid; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUB_JOINED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1008,7 +997,7 @@ class VideoRoomHandle extends Handle { jsep.e2ee = (typeof e2ee === 'boolean') ? e2ee : jsep.e2ee; const response = await this.message(body, jsep); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.STARTED && evtdata.started === 'ok') return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1026,7 +1015,7 @@ class VideoRoomHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.PAUSED && evtdata.paused === 'ok') return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1061,7 +1050,7 @@ class VideoRoomHandle extends Handle { } const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SWITCHED && evtdata.switched === 'ok') { return evtdata; } @@ -1081,7 +1070,7 @@ class VideoRoomHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.LEAVING) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1104,7 +1093,7 @@ class VideoRoomHandle extends Handle { if (unsubscribe && Array.isArray(unsubscribe)) body.unsubscribe = unsubscribe; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.UPDATED) { return evtdata; } @@ -1134,7 +1123,7 @@ class VideoRoomHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.PARTICIPANTS_LIST) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1159,7 +1148,7 @@ class VideoRoomHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.RECORDING_ENABLED_STATE) { evtdata.room = body.room; return evtdata; @@ -1186,7 +1175,7 @@ class VideoRoomHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.SUCCESS) { evtdata.room = body.room; evtdata.feed = body.id; @@ -1210,7 +1199,7 @@ class VideoRoomHandle extends Handle { }; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.EXISTS) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1231,7 +1220,7 @@ class VideoRoomHandle extends Handle { if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.ROOMS_LIST) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1302,7 +1291,7 @@ class VideoRoomHandle extends Handle { if (typeof threads === 'number') body.threads = threads; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.CREATED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1327,7 +1316,7 @@ class VideoRoomHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.DESTROYED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1354,7 +1343,7 @@ class VideoRoomHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.ALLOWED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1413,7 +1402,7 @@ class VideoRoomHandle extends Handle { if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.RTP_FWD_STARTED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1442,7 +1431,7 @@ class VideoRoomHandle extends Handle { if (typeof admin_key === 'string') body.admin_key = admin_key; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.RTP_FWD_STOPPED) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); @@ -1465,7 +1454,7 @@ class VideoRoomHandle extends Handle { if (typeof secret === 'string') body.secret = secret; const response = await this.message(body); - const { event, data: evtdata } = response._janode || {}; + const { event, data: evtdata } = this._getPluginEvent(response); if (event === PLUGIN_EVENT.RTP_FWD_LIST) return evtdata; const error = new Error(`unexpected response to ${body.request} request`); From e3e9deb68b46d1242f33f531d36adc1a9b02cdaf Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 8 Apr 2025 11:20:29 +0200 Subject: [PATCH 081/114] Fix one-off error for max_retries --- src/transport-unix.js | 2 +- src/transport-ws.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/transport-unix.js b/src/transport-unix.js index e15d3f6..86c89bc 100644 --- a/src/transport-unix.js +++ b/src/transport-unix.js @@ -189,7 +189,7 @@ class TransportUnix { /* In case of error notifies the user, but try with another address */ this._attempts++; /* Get the max number of attempts from the configuration */ - if (this._attempts >= this._connection._config.getMaxRetries()) { + if (this._attempts >= this._connection._config.getMaxRetries() + 1) { this._opening = false; const err = new Error('attempt limit exceeded'); Logger.error(`${LOG_NS} ${this.name} socket connection failed, ${err.message}`); diff --git a/src/transport-ws.js b/src/transport-ws.js index 0f34a3e..4f41dc2 100644 --- a/src/transport-ws.js +++ b/src/transport-ws.js @@ -123,7 +123,7 @@ class TransportWs { Logger.info(`${LOG_NS} ${this.name} trying connection with ${this._connection._address_iterator.currElem().url}`); return new Promise((resolve, reject) => { - const wsOptions = this._connection._config.wsOptions() || { }; + const wsOptions = this._connection._config.wsOptions() || {}; if (!wsOptions.handshakeTimeout) wsOptions.handshakeTimeout = 5000; const ws = new WebSocket( @@ -197,7 +197,7 @@ class TransportWs { /* In case of error notifies the user, but try with another address */ this._attempts++; /* Get the max number of attempts from the configuration */ - if (this._attempts >= this._connection._config.getMaxRetries()) { + if (this._attempts >= this._connection._config.getMaxRetries() + 1) { this._opening = false; const err = new Error('attempt limit exceeded'); Logger.error(`${LOG_NS} ${this.name} connection failed, ${err.message}`); From 377b9fb852850fba8a40cd0432d282200a47ffb0 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 8 Apr 2025 11:24:37 +0200 Subject: [PATCH 082/114] Clarify a bit the meaning of CONNECTION_ERROR event (e.g. unexpected disconnection) --- src/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connection.js b/src/connection.js index 9638f4c..162ecec 100644 --- a/src/connection.js +++ b/src/connection.js @@ -151,7 +151,7 @@ class Connection extends EventEmitter { /* If this event is unexpected emit an error */ const error = new Error('unexpected disconnection'); /** - * An error occurred on the connection. + * This event is emitted when the connection is closed unexpectedly. * * @event module:connection~Connection#event:CONNECTION_ERROR * @type {Error} From d169c52dff81004665302547a3042200ddc31c62 Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Tue, 8 Apr 2025 11:52:25 +0200 Subject: [PATCH 083/114] audiobridge: add support for the play_file APIs and list_announcements API (#54) --- src/plugins/audiobridge-plugin.js | 233 ++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index c00b00f..abc0558 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -32,6 +32,11 @@ const REQUEST_MUTE_PARTICIPANT = 'mute'; const REQUEST_UNMUTE_PARTICIPANT = 'unmute'; const REQUEST_MUTE_ROOM = 'unmute_room'; const REQUEST_UNMUTE_ROOM = 'unmute_room'; +const REQUEST_PLAY_FILE = 'play_file'; +const REQUEST_IS_PLAYING = 'is_playing'; +const REQUEST_STOP_FILE = 'stop_file'; +const REQUEST_STOP_ALL_FILES = 'stop_all_files'; +const REQUEST_LIST_ANNOUNCEMENTS = 'listannouncements'; /* These are the events/responses that the Janode plugin will manage */ /* Some of them will be exported in the plugin descriptor */ @@ -61,6 +66,9 @@ const PLUGIN_EVENT = { FWD_LIST: 'audiobridge_rtp_list', ALLOWED: 'audiobridge_allowed', ROOM_MUTED: 'audiobridge_room_muted', + ANNOUNCEMENTS_LIST: 'audiobridge_announcements_list', + ANNOUNCEMENT_STARTED: 'audiobridge_announcement_started', + ANNOUNCEMENT_STOPPED: 'audiobridge_announcement_stopped', SUCCESS: 'audiobridge_success', ERROR: 'audiobridge_error', }; @@ -117,6 +125,7 @@ class AudioBridgeHandle extends Handle { /* Prepare an object for the output Janode event */ const janode_event = this._newPluginEvent(janus_message); + /* Add room information if available */ if (room) janode_event.data.room = room; @@ -164,6 +173,15 @@ class AudioBridgeHandle extends Handle { if (typeof message_data.allowed !== 'undefined') { janode_event.data.list = message_data.allowed; } + if (typeof message_data.file_id !== 'undefined') { + janode_event.data.file_id = message_data.file_id; + } + if (typeof message_data.file_id_list !== 'undefined') { + janode_event.data.file_id_list = message_data.file_id_list; + } + if (typeof message_data.playing !== 'undefined') { + janode_event.data.playing = message_data.playing; + } /* In this case the "event" field of the Janode event is "success" */ janode_event.event = PLUGIN_EVENT.SUCCESS; break; @@ -264,6 +282,12 @@ class AudioBridgeHandle extends Handle { janode_event.event = PLUGIN_EVENT.FWD_LIST; break; + /* Announcements list */ + case 'announcements': + janode_event.data.announcements = message_data.announcements; + janode_event.event = PLUGIN_EVENT.ANNOUNCEMENTS_LIST; + break; + /* Talking events */ case 'talking': case 'stopped-talking': @@ -272,6 +296,13 @@ class AudioBridgeHandle extends Handle { janode_event.event = message_data.id !== this.feed ? PLUGIN_EVENT.PEER_TALKING : PLUGIN_EVENT.TALKING; break; + /* Announcement events */ + case 'announcement-started': + case 'announcement-stopped': + janode_event.data.file_id = message_data.file_id; + janode_event.event = audiobridge === 'announcement-started' ? PLUGIN_EVENT.ANNOUNCEMENT_STARTED : PLUGIN_EVENT.ANNOUNCEMENT_STOPPED; + break; + /* Generic event (e.g. errors) */ case 'event': /* AudioBridge error */ @@ -1031,6 +1062,141 @@ class AudioBridgeHandle extends Handle { throw (error); } + /** + * Play a file inside a room. + * + * @param {object} params + * @param {number|string} params.room - The involved room + * @param {string} [params.secret] - The optional secret needed to manage the room + * @param {string} [params.group] - The optional group to play in + * @param {string} [params.file_id] - The optional ID of the announcement + * @param {string} params.filename - The path to the Opus file to play + * @param {boolean} [params.loop] - Whether the file should be played in a loop + * @returns {Promise} + */ + async playFile({ room, secret, group, file_id, filename, loop }) { + const body = { + request: REQUEST_PLAY_FILE, + room, + }; + if (typeof secret === 'string') body.secret = secret; + if (typeof group === 'string') body.group = group; + if (typeof file_id === 'string') body.file_id = file_id; + if (typeof filename === 'string') body.filename = filename; + if (typeof loop === 'boolean') body.loop = loop; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) { + evtdata.room = body.room; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Check whether a file is playing inside a room. + * + * @param {object} params + * @param {number|string} params.room - The involved room + * @param {string} [params.secret] - The optional secret needed to manage the room + * @param {string} params.file_id - The involved announcement ID + * @returns {Promise} + */ + async isPlaying({ room, secret, file_id }) { + const body = { + request: REQUEST_IS_PLAYING, + room, + }; + if (typeof secret === 'string') body.secret = secret; + if (typeof file_id === 'string') body.file_id = file_id; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) { + evtdata.room = body.room; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Stop playing a file inside a room. + * + * @param {object} params + * @param {number|string} params.room - The involved room + * @param {string} [params.secret] - The optional secret needed to manage the room + * @param {string} params.file_id - The involved announcement ID + * @returns {Promise} + */ + async stopFile({ room, secret, file_id }) { + const body = { + request: REQUEST_STOP_FILE, + room, + }; + if (typeof secret === 'string') body.secret = secret; + if (typeof file_id === 'string') body.file_id = file_id; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) { + evtdata.room = body.room; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Stop playing all files inside a room. + * + * @param {object} params + * @param {number|string} params.room - The involved room + * @param {string} [params.secret] - The optional secret needed to manage the room + * @returns {Promise} + */ + async stopAllFiles({ room, secret }) { + const body = { + request: REQUEST_STOP_ALL_FILES, + room, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) { + evtdata.room = body.room; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * List announcements inside a room. + * + * @param {object} params + * @param {number|string} params.room - The room where to execute the list + * @param {string} [params.secret] - The optional secret needed for managing the room + * @returns {Promise} + */ + async listAnnouncements({ room, secret }) { + const body = { + request: REQUEST_LIST_ANNOUNCEMENTS, + room, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.ANNOUNCEMENTS_LIST) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + } /** @@ -1234,6 +1400,51 @@ class AudioBridgeHandle extends Handle { * @property {string[]} list - The updated, complete, list of allowed tokens */ +/** + * The response event for audiobridge play_file request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_PLAY_FILE_RESPONSE + * @property {number|string} room - The involved room + * @property {string} file_id - The involved file id + */ + +/** + * The response event for audiobridge is_playing request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_IS_PLAYING_RESPONSE + * @property {number|string} room - The involved room + * @property {string} file_id - The involved file id + * @property {boolean} playing - True if the file is being played + */ + +/** + * The response event for audiobridge stop_file request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_STOP_FILE_RESPONSE + * @property {number|string} room - The involved room + * @property {string} file_id - The involved file id + */ + +/** + * The response event for audiobridge stop_all_files request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_STOP_ALL_FILES_RESPONSE + * @property {number|string} room - The involved room + * @property {string[]} file_id_list - The list of file ids that was stopped + */ + +/** + * The response event for audiobridge announcements list request. + * + * @typedef {object} AUDIOBRIDGE_EVENT_ANNOUNCEMENTS_LIST + * @property {number|string} room - The involved room + * @property {object[]} announcements - The list of announcements + * @property {string} announcements[].file_id - The announcement identifier + * @property {string} announcements[].filename - The path to the Opus file + * @property {boolean} announcements[].playing - True if the announcement is playing + * @property {boolean} announcements[].loop - True if the announcement will be played in a loop + */ + /** * The exported plugin descriptor. * @@ -1255,6 +1466,8 @@ class AudioBridgeHandle extends Handle { * @property {string} EVENT.AUDIOBRIDGE_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_RESUMED} * @property {string} EVENT.AUDIOBRIDGE_PEER_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_RESUMED} * @property {string} EVENT.AUDIOBRIDGE_ROOM_MUTED {@link module:audiobridge-plugin~AUDIOBRIDGE_ROOM_MUTED} + * @property {string} EVENT.AUDIOBRIDGE_ANNOUNCEMENT_STARTED {@link module:audiobridge-plugin~AUDIOBRIDGE_ANNOUNCEMENT_STARTED} + * @property {string} EVENT.AUDIOBRIDGE_ANNOUNCEMENT_STOPPED {@link module:audiobridge-plugin~AUDIOBRIDGE_ANNOUNCEMENT_STOPPED} * @property {string} EVENT.AUDIOBRIDGE_ERROR {@link module:audiobridge-plugin~AUDIOBRIDGE_ERROR} */ export default { @@ -1412,6 +1625,26 @@ export default { */ AUDIOBRIDGE_ROOM_MUTED: PLUGIN_EVENT.ROOM_MUTED, + /** + * The announcement has been started. + * + * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ANNOUNCEMENT_STARTED + * @type {object} + * @property {number|string} room + * @property {string} file_id + */ + AUDIOBRIDGE_ANNOUNCEMENT_STARTED: PLUGIN_EVENT.ANNOUNCEMENT_STARTED, + + /** + * The announcement has been stopped. + * + * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ANNOUNCEMENT_STOPPED + * @type {object} + * @property {number|string} room + * @property {string} file_id + */ + AUDIOBRIDGE_ANNOUNCEMENT_STOPPED: PLUGIN_EVENT.ANNOUNCEMENT_STOPPED, + /** * Generic audiobridge error. * From 20a9fc4b1dab54738a805e7512bfce5f393ce16d Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 8 Apr 2025 11:55:50 +0200 Subject: [PATCH 084/114] ci: update workflow --- .github/workflows/janode-ci.yml | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/janode-ci.yml b/.github/workflows/janode-ci.yml index b20f831..19efdca 100644 --- a/.github/workflows/janode-ci.yml +++ b/.github/workflows/janode-ci.yml @@ -2,18 +2,21 @@ name: janode-ci on: push: - branches: [ master ] + branches: + - master + - test-ci pull_request: - branches: [ master ] + branches: + - master permissions: contents: read jobs: lint: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 20 - - run: npm ci - - run: npm run lint + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - run: npm ci + - run: npm run lint From cb208060bd970ff1bfdfc53cba5bbb374bc481de Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 8 Apr 2025 12:05:36 +0200 Subject: [PATCH 085/114] version: bump to v1.7.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93905a8..6678a1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.7.2", + "version": "1.7.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.7.2", + "version": "1.7.3", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index 0911d0d..c419c53 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.7.2", + "version": "1.7.3", "type": "module", "keywords": [ "janus", From 065d1dfeaff9d2012ae85a4c629f593bd491764a Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Tue, 8 Apr 2025 13:01:08 +0200 Subject: [PATCH 086/114] streaming: add support for client-side offers (#55) --- src/plugins/streaming-plugin.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index ac3b231..3184d47 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -208,10 +208,16 @@ class StreamingHandle extends Handle { * @param {boolean} [params.audio] - True to request audio * @param {boolean} [params.video] - True to request video * @param {boolean} [params.data] - True to request data + * @param {RTCSessionDescription} [params.jsep=null] - JSEP offer + * @property {boolean} [params.e2ee] - True if end-to-end enecryption is used * @param {boolean} [params.restart=false] - True to trigger a restart * @returns {Promise} */ - async watch({ id, pin, audio, video, data, restart = false }) { + async watch({ id, pin, audio, video, data, jsep = null, e2ee, restart = false }) { + if (typeof jsep === 'object' && jsep && jsep.type !== 'offer') { + const error = new Error('jsep must be an offer'); + return Promise.reject(error); + } const body = { request: REQUEST_WATCH, id, @@ -221,10 +227,12 @@ class StreamingHandle extends Handle { if (typeof video === 'boolean') body.offer_video = video; if (typeof data === 'boolean') body.offer_data = data; if (typeof restart === 'boolean') body.restart = restart; + if (jsep) + jsep.e2ee = (typeof e2ee === 'boolean') ? e2ee : jsep.e2ee; - const response = await this.message(body); - const { event, data: evtdata } = this._getPluginEvent(response);; - if (event === PLUGIN_EVENT.STATUS && (evtdata.status === 'preparing' || evtdata.status === 'updating')) { + const response = await this.message(body, jsep); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.STATUS && (evtdata.status === 'preparing' || evtdata.status === 'updating' || (jsep && evtdata.status === 'starting'))) { /* Set current mp to subscribed id */ this.mp = id; return evtdata; From b95dfd2cb2fd5d0686e5944d3ddb32b9919c1b03 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 8 Apr 2025 13:02:04 +0200 Subject: [PATCH 087/114] version: bump to v1.7.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6678a1d..85d5988 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.7.3", + "version": "1.7.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.7.3", + "version": "1.7.4", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index c419c53..bcfaa9e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.7.3", + "version": "1.7.4", "type": "module", "keywords": [ "janus", From 599b18b2227b0d7a26ea26df2316431f5f62c357 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 28 Apr 2025 13:08:27 +0200 Subject: [PATCH 088/114] Fix docs typos --- src/connection.js | 2 +- src/handle.js | 6 ++++-- src/plugins/streaming-plugin.js | 9 +++++---- src/plugins/videoroom-plugin.js | 7 ++++--- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/connection.js b/src/connection.js index 162ecec..2119a02 100644 --- a/src/connection.js +++ b/src/connection.js @@ -490,7 +490,7 @@ class Connection extends EventEmitter { * * @param {number} session_id - The session identifier * @param {number} handle_id - The handle identifier - * @returns {Promsie} The stop pcap response + * @returns {Promise} The stop pcap response */ async stopPcap(session_id, handle_id) { Logger.info(`${LOG_NS} ${this.name} requesting pcap stop for handle ${handle_id}`); diff --git a/src/handle.js b/src/handle.js index f6aaef7..ac1e96c 100644 --- a/src/handle.js +++ b/src/handle.js @@ -430,8 +430,10 @@ class Handle extends EventEmitter { * Implementations must return falsy values for unhandled events and truthy value * for handled events. * + * @param {object} _janus_message + * @returns {object} */ - handleMessage() { + handleMessage(_janus_message) { return null; } @@ -474,7 +476,7 @@ class Handle extends EventEmitter { * Send a request from this handle. * * @param {object} request - * @returns {Promise} A promsie resolving with the response to the request + * @returns {Promise} A Promise resolving with the response to the request */ async sendRequest(request) { /* Input check */ diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index 3184d47..59fcac2 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -209,7 +209,7 @@ class StreamingHandle extends Handle { * @param {boolean} [params.video] - True to request video * @param {boolean} [params.data] - True to request data * @param {RTCSessionDescription} [params.jsep=null] - JSEP offer - * @property {boolean} [params.e2ee] - True if end-to-end enecryption is used + * @param {boolean} [params.e2ee] - True if end-to-end enecryption is used * @param {boolean} [params.restart=false] - True to trigger a restart * @returns {Promise} */ @@ -245,8 +245,8 @@ class StreamingHandle extends Handle { * Start a mountpoint stream. * * @param {object} params - * @property {RTCSessionDescription} params.jsep - * @property {boolean} [params.e2ee] + * @param {RTCSessionDescription} params.jsep + * @param {boolean} [params.e2ee] * @returns {Promise} */ async start({ jsep, e2ee }) { @@ -515,7 +515,7 @@ class StreamingHandle extends Handle { * * @param {object} params * @param {number|string} params.id - * @param {boolean} [stop_recording=true] - True if the user wants to also stop the recording of a disabled moutnpoint + * @param {boolean} [params.stop_recording=true] - True if the user wants to also stop the recording of a disabled moutnpoint * @param {string} [params.secret] * @returns {Promise} */ @@ -540,6 +540,7 @@ class StreamingHandle extends Handle { * * @param {object} params * @param {number|string} [params.id=0] - The id for the new mountpoint (if omitted Janus will pick one) + * @param {string} [params.name] - A name for the mp * @param {string} [params.description] - A description for the mp * @param {string} [params.secret] - The secret that'll be needed to edit this mountpoint * @param {string} [params.pin] - The pin that'll be needed to connect to the new mountpoint diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index f6956cc..f2ab372 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -986,7 +986,7 @@ class VideoRoomHandle extends Handle { * * @param {object} params * @param {RTCSessionDescription} params.jsep - The JSEP answer - * @param {boolean} [e2ee] - True to hint an end-to-end encrypted negotiation + * @param {boolean} [params.e2ee] - True to hint an end-to-end encrypted negotiation * @returns {Promise} */ async start({ jsep, e2ee }) { @@ -1080,8 +1080,9 @@ class VideoRoomHandle extends Handle { /** * [multistream] Update a subscription. * - * @param {object[]} subscribe - The array of streams to subscribe - * @param {object[]} unsubscribe - The array of streams to unsubscribe + * @param {object} params + * @param {object[]} params.subscribe - The array of streams to subscribe + * @param {object[]} params.unsubscribe - The array of streams to unsubscribe * * @returns {Promise} */ From 1f8bdec5aa7d9b62a023c24a7d31e3fe7be066e0 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 28 Apr 2025 19:28:05 +0200 Subject: [PATCH 089/114] package.json: add jsdoc dev dependency and script to build documentation --- package-lock.json | 311 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 6 +- 2 files changed, 314 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 85d5988..38c80b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,12 +16,63 @@ "devDependencies": { "@eslint/js": "^9.4.0", "eslint": "^9.4.0", - "globals": "^15.4.0" + "globals": "^15.4.0", + "jsdoc": "^4.0.4" }, "engines": { "node": " >=18.18.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -229,6 +280,19 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@jsdoc/salty": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz", + "integrity": "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -243,6 +307,31 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -322,6 +411,13 @@ "file-uri-to-path": "1.0.0" } }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -343,6 +439,19 @@ "node": ">=6" } }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -427,6 +536,19 @@ "dev": true, "license": "MIT" }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -698,6 +820,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -797,6 +926,56 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", + "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^14.1.1", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -828,6 +1007,16 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -842,6 +1031,16 @@ "node": ">= 0.8.0" } }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -858,6 +1057,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -865,6 +1071,55 @@ "dev": true, "license": "MIT" }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -878,6 +1133,19 @@ "node": "*" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1001,6 +1269,26 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -1073,6 +1361,20 @@ "node": ">= 0.8.0" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "dev": true, + "license": "MIT" + }, "node_modules/unix-dgram": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.6.tgz", @@ -1144,6 +1446,13 @@ } } }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index bcfaa9e..f5a05dd 100644 --- a/package.json +++ b/package.json @@ -43,13 +43,15 @@ "devDependencies": { "@eslint/js": "^9.4.0", "eslint": "^9.4.0", - "globals": "^15.4.0" + "globals": "^15.4.0", + "jsdoc": "^4.0.4" }, "engines": { "node": " >=18.18.0" }, "scripts": { "build": "npm install --omit=dev", - "lint": "npx eslint --debug" + "lint": "npx eslint --debug", + "build-docs": "npx jsdoc -r src" } } From 8ebf66e5f98249d764bbef527d0da07c4d5773b9 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 28 Apr 2025 19:32:09 +0200 Subject: [PATCH 090/114] docs: fix typo in videoroom --- src/plugins/videoroom-plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index f2ab372..7dd2adb 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -1789,7 +1789,7 @@ export default { /** * A handle received a slow link notification. * - * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DISPLAY + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SLOWLINK * @type {object} * @property {number|string} room - The involved room * @property {number|string} feed - The feed of the peer that change display name From 28c9ccd58eb783096912ed115fe561df31f6f5d0 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 28 Apr 2025 19:42:43 +0200 Subject: [PATCH 091/114] package.json: update build-docs script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5a05dd..c816845 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,6 @@ "scripts": { "build": "npm install --omit=dev", "lint": "npx eslint --debug", - "build-docs": "npx jsdoc -r src" + "build-docs": "npx jsdoc --recurse --pedantic --verbose --destination ./out src/" } } From 424695ebb9c40f1557dc72533dbbc5088254cdc9 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 29 Apr 2025 17:54:09 +0200 Subject: [PATCH 092/114] gitignore: update --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index eeff83f..1130b23 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules build out +docs .vscode config.js @@ -14,3 +15,4 @@ bundle.js !.eslintrc.json !package.json !package-lock.json +!jsdoc.json From 079ead768201a2d8b7f31f5a8dbf1e6ca5582048 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 29 Apr 2025 18:02:08 +0200 Subject: [PATCH 093/114] docs: huge refactoring. Use a nicer template. --- jsdoc.json | 31 +++ package-lock.json | 339 ++++++++++++++++++++++++++++++ package.json | 3 +- src/configuration.js | 2 +- src/connection.js | 36 ++-- src/handle.js | 67 +++--- src/janode.js | 29 +-- src/plugins/audiobridge-plugin.js | 178 ++++++++-------- src/plugins/echotest-plugin.js | 27 +-- src/plugins/streaming-plugin.js | 70 +++--- src/plugins/videoroom-plugin.js | 169 +++++++++------ src/protocol.js | 27 ++- src/session.js | 13 +- src/tmanager.js | 18 +- src/transport-unix.js | 16 +- src/transport-ws.js | 8 +- src/utils/logger.js | 117 ++++++++--- src/utils/utils.js | 20 +- 18 files changed, 819 insertions(+), 351 deletions(-) create mode 100644 jsdoc.json diff --git a/jsdoc.json b/jsdoc.json new file mode 100644 index 0000000..8574aa8 --- /dev/null +++ b/jsdoc.json @@ -0,0 +1,31 @@ +{ + "opts": { + "encoding": "utf8", + "package": "./package.json", + "readme": "./README.md", + "pedantic": true, + "recurse": true, + "verbose": true, + "template": "./node_modules/clean-jsdoc-theme", + "theme_opts": { + "default_theme": "dark", + "menu": [ + { + "title": "Home", + "link": "index.html" + }, + { + "title": "GitHub", + "link": "https://github.com/meetecho/janode" + } + ], + "search": true, + "sort": true, + "exclude_inherited": true + } + }, + "markdown": { + "hardwrap": false, + "idInHeadings": true + } +} diff --git a/package-lock.json b/package-lock.json index 38c80b7..a153d37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ }, "devDependencies": { "@eslint/js": "^9.4.0", + "clean-jsdoc-theme": "^4.3.0", "eslint": "^9.4.0", "globals": "^15.4.0", "jsdoc": "^4.0.4" @@ -280,6 +281,70 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jsdoc/salty": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz", @@ -429,6 +494,13 @@ "concat-map": "0.0.1" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -439,6 +511,17 @@ "node": ">=6" } }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -469,6 +552,37 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-jsdoc-theme": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/clean-jsdoc-theme/-/clean-jsdoc-theme-4.3.0.tgz", + "integrity": "sha512-QMrBdZ2KdPt6V2Ytg7dIt0/q32U4COpxvR0UDhPjRRKRL0o0MvRCR5YpY37/4rPF1SI1AYEKAWyof7ndCb/dzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsdoc/salty": "^0.2.4", + "fs-extra": "^10.1.0", + "html-minifier-terser": "^7.2.0", + "klaw-sync": "^6.0.0", + "lodash": "^4.17.21", + "showdown": "^2.1.0" + }, + "peerDependencies": { + "jsdoc": ">=3.x <=4.x" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -489,6 +603,16 @@ "dev": true, "license": "MIT" }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -536,6 +660,17 @@ "dev": true, "license": "MIT" }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -794,6 +929,21 @@ "dev": true, "license": "ISC" }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -837,6 +987,28 @@ "node": ">=8" } }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -997,6 +1169,19 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -1017,6 +1202,16 @@ "graceful-fs": "^4.1.9" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -1071,6 +1266,16 @@ "dev": true, "license": "MIT" }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", @@ -1166,6 +1371,17 @@ "dev": true, "license": "MIT" }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -1216,6 +1432,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -1229,6 +1456,17 @@ "node": ">=6" } }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -1279,6 +1517,16 @@ "node": ">=6" } }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/requizzle": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", @@ -1322,6 +1570,54 @@ "node": ">=8" } }, + "node_modules/showdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", + "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^9.0.0" + }, + "bin": { + "showdown": "bin/showdown.js" + }, + "funding": { + "type": "individual", + "url": "https://www.paypal.me/tiviesantos" + } + }, + "node_modules/showdown/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1348,6 +1644,39 @@ "node": ">=8" } }, + "node_modules/terser": { + "version": "5.39.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", + "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -1375,6 +1704,16 @@ "dev": true, "license": "MIT" }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unix-dgram": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.6.tgz", diff --git a/package.json b/package.json index c816845..3a989ba 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ }, "devDependencies": { "@eslint/js": "^9.4.0", + "clean-jsdoc-theme": "^4.3.0", "eslint": "^9.4.0", "globals": "^15.4.0", "jsdoc": "^4.0.4" @@ -52,6 +53,6 @@ "scripts": { "build": "npm install --omit=dev", "lint": "npx eslint --debug", - "build-docs": "npx jsdoc --recurse --pedantic --verbose --destination ./out src/" + "build-docs": "rm -rf ./docs && npx jsdoc -c ./jsdoc.json --destination ./docs ./src" } } diff --git a/src/configuration.js b/src/configuration.js index 0845ab8..2709bb7 100644 --- a/src/configuration.js +++ b/src/configuration.js @@ -78,7 +78,7 @@ class Configuration { /** * Return the specific WebSocket transport options. * - * @returns {object} + * @returns {Object} */ wsOptions() { return this.ws_options; diff --git a/src/connection.js b/src/connection.js index 2119a02..71e7a62 100644 --- a/src/connection.js +++ b/src/connection.js @@ -3,7 +3,7 @@ /** * This module contains the Connection class definition. * @module connection - * @access private + * @private */ import { EventEmitter } from 'events'; @@ -87,13 +87,9 @@ class Connection extends EventEmitter { this.name = `[${this.id}]`; /** - * The internal transport that will be used for the connection. + * The transport used by this connection. * - * @typedef {object} Transport - * @property {function} open - * @property {function} close - * @property {function} send - * @property {function} getRemoteHostname + * @private */ this._transport = { open: async _ => { throw new Error('transport does not implement the "open" function'); }, @@ -139,10 +135,10 @@ class Connection extends EventEmitter { if (graceful) { /* This is a greceful teardown */ /** - * The connection has been closed. + * The connection has been gracefully closed. * * @event module:connection~Connection#event:CONNECTION_CLOSED - * @type {object} + * @type {Object} * @property {number} id - The connection identifier */ this.emit(JANODE.EVENT.CONNECTION_CLOSED, { id: this.id }); @@ -151,7 +147,7 @@ class Connection extends EventEmitter { /* If this event is unexpected emit an error */ const error = new Error('unexpected disconnection'); /** - * This event is emitted when the connection is closed unexpectedly. + * The connection has been unexpectedly closed. * * @event module:connection~Connection#event:CONNECTION_ERROR * @type {Error} @@ -180,7 +176,7 @@ class Connection extends EventEmitter { * the transaction will be closed. * * @private - * @param {object} janus_message + * @param {Object} janus_message */ _handleMessage(janus_message) { const { session_id, transaction, janus } = janus_message; @@ -239,7 +235,7 @@ class Connection extends EventEmitter { * Decorate request with apisecret, token and transaction (if missing). * * @private - * @param {object} request + * @param {Object} request */ _decorateRequest(request) { request.transaction = request.transaction || getNumericID(); @@ -266,8 +262,8 @@ class Connection extends EventEmitter { /** * Send a request from this connection using the transport defined send method. * - * @param {object} request - The request to be sent - * @returns {Promise} A promise resolving with a response from Janus + * @param {Object} request - The request to be sent + * @returns {Promise} A promise resolving with a response from Janus */ async sendRequest(request) { /* Add connection properties */ @@ -342,7 +338,7 @@ class Connection extends EventEmitter { /** * Janus GET INFO API. * - * @returns {Promise} The Get Info response + * @returns {Promise} The Get Info response * * @example * @@ -368,7 +364,7 @@ class Connection extends EventEmitter { /** * (Admin API) List the sessions in a janus instance. * - * @returns {Promise} + * @returns {Promise} * * @example * @@ -389,7 +385,7 @@ class Connection extends EventEmitter { * (Admin API) List the handles in a session. * * @param {number} session_id - The identifier of the session - * @returns {Promise} + * @returns {Promise} * * @example * @@ -416,7 +412,7 @@ class Connection extends EventEmitter { * * @param {number} session_id - The session identifier * @param {number} handle_id - The handle identifier - * @returns {Promise} The Get Handle Info response + * @returns {Promise} The Get Handle Info response * * @example * @@ -452,7 +448,7 @@ class Connection extends EventEmitter { * @param {string} folder - The folder in which save the pcap * @param {string} filename - The pcap file name * @param {number} [truncate] - Number of bytes to truncate the pcap to - * @returns {Promise} The start pcap response + * @returns {Promise} The start pcap response */ async startPcap(session_id, handle_id, folder, filename, truncate) { Logger.info(`${LOG_NS} ${this.name} requesting pcap start for handle ${handle_id}`); @@ -490,7 +486,7 @@ class Connection extends EventEmitter { * * @param {number} session_id - The session identifier * @param {number} handle_id - The handle identifier - * @returns {Promise} The stop pcap response + * @returns {Promise} The stop pcap response */ async stopPcap(session_id, handle_id) { Logger.info(`${LOG_NS} ${this.name} requesting pcap stop for handle ${handle_id}`); diff --git a/src/handle.js b/src/handle.js index ac1e96c..715c4b4 100644 --- a/src/handle.js +++ b/src/handle.js @@ -3,7 +3,7 @@ /** * This module contains the Handle class definition. * @module handle - * @access private + * @private */ import { EventEmitter } from 'events'; @@ -14,6 +14,7 @@ import { getNumericID } from './utils/utils.js'; import { JANUS, JANODE, isAckData, isResponseData, isErrorData } from './protocol.js'; const PLUGIN_EVENT_SYM = Symbol('plugin_event'); + /** * Class representing a Janode handle.
* @@ -39,7 +40,7 @@ class Handle extends EventEmitter { * The transaction manager used by this handle. * * @private - * @type {TransactionManager} + * @type {module:tmanager~TransactionManager} */ this._tm = session._tm; // keep track of pending requests @@ -114,7 +115,7 @@ class Handle extends EventEmitter { * The handle has been detached. * * @event module:handle~Handle#event:HANDLE_DETACHED - * @type {object} + * @type {Object} * @property {number} id - The handle identifier */ this.emit(JANODE.EVENT.HANDLE_DETACHED, { id: this.id }); @@ -169,7 +170,7 @@ class Handle extends EventEmitter { * Generic Janus API events like `detached`, `hangup` etc. are handled here. * * @private - * @param {object} janus_message + * @param {Object} janus_message */ _handleMessage(janus_message) { const { transaction, janus } = janus_message; @@ -269,7 +270,7 @@ class Handle extends EventEmitter { * The handle has detected an ICE failure. * * @event module:handle~Handle#event:HANDLE_ICE_FAILED - * @type {object} + * @type {Object} */ this.emit(JANODE.EVENT.HANDLE_ICE_FAILED, janode_event_data); break; @@ -283,7 +284,7 @@ class Handle extends EventEmitter { * The handle WebRTC connection has been closed. * * @event module:handle~Handle#event:HANDLE_HANGUP - * @type {object} + * @type {Object} * @property {string} [reason] - The reason of the hangup (e.g. ICE failed) */ this.emit(JANODE.EVENT.HANDLE_HANGUP, janode_event_data); @@ -302,7 +303,7 @@ class Handle extends EventEmitter { * The handle received a media notification. * * @event module:handle~Handle#event:HANDLE_MEDIA - * @type {object} + * @type {Object} * @property {string} type - The kind of media (audio/video) * @property {boolean} receiving - True if Janus is receiving media * @property {string} [mid] - The involved mid @@ -319,6 +320,7 @@ class Handle extends EventEmitter { * The handle WebRTC connection is up. * * @event module:handle~Handle#event:HANDLE_WEBRTCUP + * @type {Object} */ this.emit(JANODE.EVENT.HANDLE_WEBRTCUP, janode_event_data); break; @@ -335,7 +337,7 @@ class Handle extends EventEmitter { * The handle has received a slowlink notification. * * @event module:handle~Handle#event:HANDLE_SLOWLINK - * @type {object} + * @type {Object} * @property {boolean} uplink - The direction of the slow link * @property {string} media - The media kind (audio/video) * @property {string} [mid] - The involved stream mid @@ -347,17 +349,6 @@ class Handle extends EventEmitter { /* Trickle from Janus */ case JANUS.EVENT.TRICKLE: { - /** - * The handle has received a trickle notification. - * - * @event module:handle~Handle#event:HANDLE_TRICKLE - * @type {object} - * @property {boolean} [completed] - If true, this notifies the end of triclking (the other fields of the event are missing in this case) - * @property {string} [sdpMid] - The mid the candidate refers to - * @property {number} [sdpMLineIndex] - The m-line the candidate refers to - * @property {string} [candidate] - The candidate string - */ - const { completed, sdpMid, sdpMLineIndex, candidate } = janus_message.candidate; if (!completed) { janode_event_data.sdpMid = sdpMid; @@ -368,6 +359,16 @@ class Handle extends EventEmitter { janode_event_data.completed = true; } + /** + * The handle has received a trickle notification. + * + * @event module:handle~Handle#event:HANDLE_TRICKLE + * @type {Object} + * @property {boolean} [completed] - If true, this notifies the end of triclking (the other fields of the event are missing in this case) + * @property {string} [sdpMid] - The mid the candidate refers to + * @property {number} [sdpMLineIndex] - The m-line the candidate refers to + * @property {string} [candidate] - The candidate string + */ this.emit(JANODE.EVENT.HANDLE_TRICKLE, janode_event_data); break; } @@ -381,7 +382,7 @@ class Handle extends EventEmitter { * Decorate request with handle id and transaction (if missing). * * @private - * @param {object} request + * @param {Object} request */ _decorateRequest(request) { request.transaction = request.transaction || getNumericID(); @@ -392,8 +393,8 @@ class Handle extends EventEmitter { * Helper method used by plugins to create a new plugin event and assign it to a janus message. * * @private - * @param {object} janus_message - * @returns {object} + * @param {Object} janus_message + * @returns {Object} */ _newPluginEvent(janus_message) { /* Prepare an object for the output Janode event */ @@ -418,8 +419,8 @@ class Handle extends EventEmitter { * Helper method used by plugins to get an assigned plugin eventfrom a handled janus message. * * @private - * @param {object} janus_message - * @returns {object} + * @param {Object} janus_message + * @returns {Object} */ _getPluginEvent(janus_message) { return janus_message[PLUGIN_EVENT_SYM] || {}; @@ -430,8 +431,8 @@ class Handle extends EventEmitter { * Implementations must return falsy values for unhandled events and truthy value * for handled events. * - * @param {object} _janus_message - * @returns {object} + * @param {Object} _janus_message + * @returns {Object} */ handleMessage(_janus_message) { return null; @@ -451,7 +452,7 @@ class Handle extends EventEmitter { * Helper to close a transaction with error. * * @property {string} id - The transaction id - * @property {object} error - The error object + * @property {Error} error - The error object * @returns {void} */ closeTransactionWithError(id, error) { @@ -463,7 +464,7 @@ class Handle extends EventEmitter { * Helper to close a transaction with success. * * @property {string} id - The transaction id - * @property {object} [data] - The callback success data + * @property {Object} [data] - The callback success data * @returns {void} */ closeTransactionWithSuccess(id, data) { @@ -475,8 +476,8 @@ class Handle extends EventEmitter { /** * Send a request from this handle. * - * @param {object} request - * @returns {Promise} A Promise resolving with the response to the request + * @param {Object} request + * @returns {Promise} A Promise resolving with the response to the request */ async sendRequest(request) { /* Input check */ @@ -546,7 +547,7 @@ class Handle extends EventEmitter { /** * Close the peer connection associated to this handle. * - * @returns {Promise} + * @returns {Promise} */ async hangup() { const request = { @@ -613,9 +614,9 @@ class Handle extends EventEmitter { /** * Send a `message` to Janus from this handle, with given body and optional jsep. * - * @param {object} body - The body of the message + * @param {Object} body - The body of the message * @param {RTCSessionDescription} [jsep] - * @returns {Promise} A promise resolving with the response to the message + * @returns {Promise} A promise resolving with the response to the message * * @example * // This is a plugin that sends a message with a custom body diff --git a/src/janode.js b/src/janode.js index 297aab8..3461af7 100644 --- a/src/janode.js +++ b/src/janode.js @@ -17,7 +17,7 @@ const { EVENT } = JANODE_PROTO; /** * An object describing a janus server (e.g. url, secret). * - * @typedef {object} ServerObjectConf + * @typedef {Object} ServerObjectConf * @property {string} url - The URL to reach this server API * @property {string} apisecret - The API secret for this server * @property {string} [token] - The optional Janus API token @@ -26,22 +26,22 @@ const { EVENT } = JANODE_PROTO; /** * The configuration passed by the user. * - * @typedef {object} RawConfiguration + * @typedef {Object} RawConfiguration * @property {string} [server_key] - The key used to refer to this server in Janode.connect * @property {module:janode~ServerObjectConf[]|module:janode~ServerObjectConf} address - The server to connect to * @property {number} [retry_time_secs=10] - The seconds between any connection attempts * @property {number} [max_retries=5] - The maximum number of retries before issuing a connection error * @property {boolean} [is_admin=false] - True if the connection is dedicated to the Janus Admin API - * @property {object} [ws_options] - Specific WebSocket transport options + * @property {Object} [ws_options] - Specific WebSocket transport options */ /** * The plugin descriptor used when attaching a plugin from a session. * - * @typedef {object} PluginDescriptor + * @typedef {Object} PluginDescriptor * @property {string} id - The plugin id used when sending the attach request to Janus * @property {module:handle~Handle} [Handle] - The class implementing the handle - * @property {object} [EVENT] - The object with the list of events emitted by the plugin + * @property {Object} [EVENT] - The object containing the events emitted by the plugin */ /** @@ -106,7 +106,6 @@ const { EVENT } = JANODE_PROTO; */ const connect = (config = {}, key = null) => { Logger.info(`${LOG_NS} creating new connection`); - const janus_server_list = Array.isArray(config) ? config : [config]; let index = 0; if (typeof key === 'number') @@ -134,28 +133,14 @@ export default { /** * The Logger used in Janode. * - * @type {object} - * @property {function} debug - Print out a debug message - * @property {function} verbose - Print out a verbose message - * @property {function} info - Print out an info message - * @property {function} warn - Print out a warning message - * @property {function} error - Print out an error message - * @property {function} setLevel - Set logger level + * @type {module:logger~Logger} */ Logger, /** * Events emitted by Janode * - * @type {object} - * @property {string} CONNECTION_CLOSED - {@link module:connection~Connection#event:CONNECTION_CLOSED} - * @property {string} SESSION_DESTROYED - {@link module:session~Session#event:SESSION_DESTROYED} - * @property {string} HANDLE_DETACHED - {@link module:handle~Handle#event:HANDLE_DETACHED} - * @property {string} HANDLE_HANGUP - {@link module:handle~Handle#event:HANDLE_HANGUP} - * @property {string} HANDLE_MEDIA - {@link module:handle~Handle#event:HANDLE_MEDIA} - * @property {string} HANDLE_WEBRTCUP - {@link module:handle~Handle#event:HANDLE_WEBRTCUP} - * @property {string} HANDLE_SLOWLINK - {@link module:handle~Handle#event:HANDLE_SLOWLINK} - * @property {string} CONNECTION_ERROR - {@link module:connection~Connection#event:CONNECTION_ERROR} + * @type {module:protocol~JanodeCoreEvents} */ EVENT, }; diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index abc0558..c2fb175 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -81,6 +81,7 @@ const PLUGIN_EVENT = { * Moreover it defines many methods to support AudioBridge operations. * * @hideconstructor + * @extends module:handle~Handle */ class AudioBridgeHandle extends Handle { /** @@ -111,8 +112,8 @@ class AudioBridgeHandle extends Handle { * The custom "handleMessage" needed for handling AudioBridge messages. * * @private - * @param {object} janus_message - * @returns {object} A falsy value for unhandled events, a truthy value for handled events + * @param {Object} janus_message + * @returns {Object} A falsy value for unhandled events, a truthy value for handled events */ handleMessage(janus_message) { const { plugindata, transaction } = janus_message; @@ -418,7 +419,7 @@ class AudioBridgeHandle extends Handle { /** * Join an audiobridge room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room to join * @param {number|string} [params.feed] - The feed identifier for the participant, picked by Janus if omitted * @param {string} [params.display] - The display name to use @@ -469,7 +470,7 @@ class AudioBridgeHandle extends Handle { /** * Configure an audiobridge handle. * - * @param {object} params + * @param {Object} params * @param {string} [params.display] - The display name to use * @param {boolean} [params.muted] - Set muted status * @param {number} [params.quality] - Set opus quality @@ -568,7 +569,7 @@ class AudioBridgeHandle extends Handle { /** * List participants inside a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where to execute the list * @param {string} [params.secret] - The optional secret needed for managing the room * @returns {Promise} @@ -591,7 +592,7 @@ class AudioBridgeHandle extends Handle { /** * Kick an user out from a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {number|string} params.feed - The feed to kick out * @param {string} [params.secret] - The optional secret needed for managing the room @@ -620,7 +621,7 @@ class AudioBridgeHandle extends Handle { /** * Check if a room exists. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @returns {Promise} */ @@ -659,7 +660,7 @@ class AudioBridgeHandle extends Handle { /** * Create an audiobridge room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room identifier * @param {string} [params.description] - A room description * @param {boolean} [params.permanent] - Set to true to persist the room in the Janus config file @@ -719,7 +720,7 @@ class AudioBridgeHandle extends Handle { /** * Destroy an audiobridge room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room to destroy * @param {boolean} [params.permanent] - Set to true to remove the room from the Janus config file * @param {string} [params.secret] - The optional secret needed to manage the room @@ -744,7 +745,7 @@ class AudioBridgeHandle extends Handle { /** * Enable/disable mixed audio recording. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room identifier * @param {boolean} params.record - Enable/disable recording * @param {string} [params.secret] - The secret to be used when managing the room @@ -775,7 +776,7 @@ class AudioBridgeHandle extends Handle { /** * Edit an audiobridge token list. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {"enable"|"disable"|"add"|"remove"} params.action - The action to perform * @param {string[]} params.list - The list of tokens to add/remove @@ -802,7 +803,7 @@ class AudioBridgeHandle extends Handle { /** * Start a RTP forwarder. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {boolean} [params.always] - Whether silence should be forwarded when the room is empty * @param {string} params.host - The host to forward to @@ -843,7 +844,7 @@ class AudioBridgeHandle extends Handle { /** * Stop a RTP forwarder. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {number} params.stream - The forwarder identifier to stop * @param {string} [params.secret] - The optional secret needed to manage the room @@ -870,7 +871,7 @@ class AudioBridgeHandle extends Handle { /** * List active forwarders. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {string} [params.secret] - The optional secret needed to manage the room * @param {string} [params.admin_key] - The admin key needed for invoking the API @@ -895,7 +896,7 @@ class AudioBridgeHandle extends Handle { /** * Mute an user in the audiobridge. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {number|string} params.feed - The feed to mute * @param {string} [params.secret] - The optional secret needed for managing the room @@ -924,7 +925,7 @@ class AudioBridgeHandle extends Handle { /** * Unmute an user in the audiobridge. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {number|string} params.feed - The feed to unmute * @param {string} [params.secret] - The optional secret needed for managing the room @@ -953,7 +954,7 @@ class AudioBridgeHandle extends Handle { /** * Mute the given room for every participant. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {string} [params.secret] - The optional secret needed to manage the room * @returns {Promise} @@ -978,7 +979,7 @@ class AudioBridgeHandle extends Handle { /** * Unmute the given room for every participant. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {string} [params.secret] - The optional secret needed to manage the room * @returns {Promise} @@ -1003,7 +1004,7 @@ class AudioBridgeHandle extends Handle { /** * Suspend an audiobridge participant. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {number|string} params.feed - The feed id to be suspended * @param {boolean} [params.stop_record] - Whether the recording of this participant should be stopped too @@ -1034,7 +1035,7 @@ class AudioBridgeHandle extends Handle { /** * Resume an audiobridge participant after a suspend. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {number|string} params.feed - The feed id to be resumed * @param {boolean} [params.record] - Whether to start recording this resumed feed @@ -1065,7 +1066,7 @@ class AudioBridgeHandle extends Handle { /** * Play a file inside a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {string} [params.secret] - The optional secret needed to manage the room * @param {string} [params.group] - The optional group to play in @@ -1098,7 +1099,7 @@ class AudioBridgeHandle extends Handle { /** * Check whether a file is playing inside a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {string} [params.secret] - The optional secret needed to manage the room * @param {string} params.file_id - The involved announcement ID @@ -1125,7 +1126,7 @@ class AudioBridgeHandle extends Handle { /** * Stop playing a file inside a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {string} [params.secret] - The optional secret needed to manage the room * @param {string} params.file_id - The involved announcement ID @@ -1152,7 +1153,7 @@ class AudioBridgeHandle extends Handle { /** * Stop playing all files inside a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The involved room * @param {string} [params.secret] - The optional secret needed to manage the room * @returns {Promise} @@ -1177,7 +1178,7 @@ class AudioBridgeHandle extends Handle { /** * List announcements inside a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where to execute the list * @param {string} [params.secret] - The optional secret needed for managing the room * @returns {Promise} @@ -1204,11 +1205,11 @@ class AudioBridgeHandle extends Handle { * {@link https://janus.conf.meetecho.com/docs/audiobridge.html} * * @private - * @typedef {object} AudioBridgeData + * @typedef {Object} AudioBridgeData */ /** - * @typedef {object} RtpParticipant + * @typedef {Object} RtpParticipant * @property {string} ip - IP address you want media to be sent to * @property {number} port - The port you want media to be sent to * @property {number} payload_type - The payload type to use for RTP packets @@ -1217,7 +1218,7 @@ class AudioBridgeHandle extends Handle { /** * The response event to a join request. * - * @typedef {object} AUDIOBRIDGE_EVENT_JOINED + * @typedef {Object} AUDIOBRIDGE_EVENT_JOINED * @property {number|string} room - The involved room * @property {number|string} feed - The feed identifier * @property {module:audiobridge-plugin~RtpParticipant} [rtp_participant] - The descriptor in case this is a plain RTP participant @@ -1231,7 +1232,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for configure request. * - * @typedef {object} AUDIOBRIDGE_EVENT_CONFIGURED + * @typedef {Object} AUDIOBRIDGE_EVENT_CONFIGURED * @property {number|string} room - The involved room * @property {number|string} feed - The feed identifier * @property {string} [display] - The display name, if available @@ -1248,7 +1249,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge hangup request. * - * @typedef {object} AUDIOBRIDGE_EVENT_AUDIO_HANGINGUP + * @typedef {Object} AUDIOBRIDGE_EVENT_AUDIO_HANGINGUP * @property {number|string} room - The involved room * @property {number|string} feed - The feed that is being hung up */ @@ -1256,7 +1257,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge leave request. * - * @typedef {object} AUDIOBRIDGE_EVENT_LEAVING + * @typedef {Object} AUDIOBRIDGE_EVENT_LEAVING * @property {number|string} room - The involved room * @property {number|string} feed- The feed that is leaving */ @@ -1264,7 +1265,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge participants list request. * - * @typedef {object} AUDIOBRIDGE_EVENT_PARTICIPANTS_LIST + * @typedef {Object} AUDIOBRIDGE_EVENT_PARTICIPANTS_LIST * @property {number|string} room - The involved room * @property {object[]} participants - The list of participants * @property {number|string} participants[].feed - The participant feed identifier @@ -1278,7 +1279,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge participant kick request. * - * @typedef {object} AUDIOBRIDGE_EVENT_KICK_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_KICK_RESPONSE * @property {number|string} room - The involved room * @property {number|string} feed - The feed that has been kicked out */ @@ -1286,7 +1287,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge room exists request. * - * @typedef {object} AUDIOBRIDGE_EVENT_EXISTS + * @typedef {Object} AUDIOBRIDGE_EVENT_EXISTS * @property {number|string} room - The involved room * @property {boolean} exists - True if the rooms exists */ @@ -1294,16 +1295,16 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge room list request. * - * @typedef {object} AUDIOBRIDGE_EVENT_ROOMS_LIST + * @typedef {Object} AUDIOBRIDGE_EVENT_ROOMS_LIST * @property {object[]} list - The list of the rooms as returned by Janus */ /** * The response event for audiobridge forwarder start request. * - * @typedef {object} AUDIOBRIDGE_EVENT_RTP_FWD + * @typedef {Object} AUDIOBRIDGE_EVENT_RTP_FWD * @property {number|string} room - The involved room - * @property {object} forwarder - Forwarder descriptor + * @property {Object} forwarder - Forwarder descriptor * @property {string} forwarder.host - The target host * @property {number} forwarder.audio_port - The target port * @property {number} forwarder.audio_stream - The identifier of the forwarder @@ -1313,7 +1314,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge room create request. * - * @typedef {object} AUDIOBRIDGE_EVENT_CREATED + * @typedef {Object} AUDIOBRIDGE_EVENT_CREATED * @property {number|string} room - The created room * @property {boolean} permanent - True if the room is being persisted in the Janus config file */ @@ -1321,14 +1322,14 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge room destroy request. * - * @typedef {object} AUDIOBRIDGE_EVENT_DESTROYED + * @typedef {Object} AUDIOBRIDGE_EVENT_DESTROYED * @property {number|string} room - The destroyed room */ /** * The response event for audiobridge ACL token edit request. * - * @typedef {object} AUDIOBRIDGE_EVENT_RECORDING + * @typedef {Object} AUDIOBRIDGE_EVENT_RECORDING * @property {number|string} room - The involved room * @property {boolean} record - Wheter recording is active or not */ @@ -1336,7 +1337,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge forwarders list request. * - * @typedef {object} AUDIOBRIDGE_EVENT_FWD_LIST + * @typedef {Object} AUDIOBRIDGE_EVENT_FWD_LIST * @property {number|string} room - The involved room * @property {object[]} forwarders - The list of forwarders * @property {string} forwarders[].host - The target host @@ -1349,7 +1350,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge mute participant request. * - * @typedef {object} AUDIOBRIDGE_EVENT_MUTE_PARTICIPANT_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_MUTE_PARTICIPANT_RESPONSE * @property {number|string} room - The involved room * @property {number|string} feed - The involved feed id */ @@ -1357,7 +1358,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge unmute participant request. * - * @typedef {object} AUDIOBRIDGE_EVENT_UNMUTE_PARTICIPANT_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_UNMUTE_PARTICIPANT_RESPONSE * @property {number|string} room - The involved room * @property {number|string} feed - The involved feed id */ @@ -1365,21 +1366,21 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge mute room request. * - * @typedef {object} AUDIOBRIDGE_EVENT_MUTE_ROOM_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_MUTE_ROOM_RESPONSE * @property {number|string} room - The involved room */ /** * The response event for audiobridge unmute room request. * - * @typedef {object} AUDIOBRIDGE_EVENT_UNMUTE_ROOM_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_UNMUTE_ROOM_RESPONSE * @property {number|string} room - The involved room */ /** * The response event for audiobridge suspend request. * - * @typedef {object} AUDIOBRIDGE_EVENT_SUSPEND_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_SUSPEND_RESPONSE * @property {number|string} room - The involved room * @property {number|string} feed - The involved feed id */ @@ -1387,7 +1388,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge resume request. * - * @typedef {object} AUDIOBRIDGE_EVENT_RESUME_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_RESUME_RESPONSE * @property {number|string} room - The involved room * @property {number|string} feed - The involved feed id */ @@ -1395,7 +1396,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge ACL token edit request. * - * @typedef {object} AUDIOBRIDGE_EVENT_ALLOWED + * @typedef {Object} AUDIOBRIDGE_EVENT_ALLOWED * @property {number|string} room - The involved room * @property {string[]} list - The updated, complete, list of allowed tokens */ @@ -1403,7 +1404,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge play_file request. * - * @typedef {object} AUDIOBRIDGE_EVENT_PLAY_FILE_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_PLAY_FILE_RESPONSE * @property {number|string} room - The involved room * @property {string} file_id - The involved file id */ @@ -1411,7 +1412,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge is_playing request. * - * @typedef {object} AUDIOBRIDGE_EVENT_IS_PLAYING_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_IS_PLAYING_RESPONSE * @property {number|string} room - The involved room * @property {string} file_id - The involved file id * @property {boolean} playing - True if the file is being played @@ -1420,7 +1421,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge stop_file request. * - * @typedef {object} AUDIOBRIDGE_EVENT_STOP_FILE_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_STOP_FILE_RESPONSE * @property {number|string} room - The involved room * @property {string} file_id - The involved file id */ @@ -1428,7 +1429,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge stop_all_files request. * - * @typedef {object} AUDIOBRIDGE_EVENT_STOP_ALL_FILES_RESPONSE + * @typedef {Object} AUDIOBRIDGE_EVENT_STOP_ALL_FILES_RESPONSE * @property {number|string} room - The involved room * @property {string[]} file_id_list - The list of file ids that was stopped */ @@ -1436,7 +1437,7 @@ class AudioBridgeHandle extends Handle { /** * The response event for audiobridge announcements list request. * - * @typedef {object} AUDIOBRIDGE_EVENT_ANNOUNCEMENTS_LIST + * @typedef {Object} AUDIOBRIDGE_EVENT_ANNOUNCEMENTS_LIST * @property {number|string} room - The involved room * @property {object[]} announcements - The list of announcements * @property {string} announcements[].file_id - The announcement identifier @@ -1448,27 +1449,27 @@ class AudioBridgeHandle extends Handle { /** * The exported plugin descriptor. * - * @type {object} + * @type {Object} * @property {string} id - The plugin identifier used when attaching to Janus * @property {module:audiobridge-plugin~AudioBridgeHandle} Handle - The custom class implementing the plugin - * @property {object} EVENT - The events emitted by the plugin - * @property {string} EVENT.AUDIOBRIDGE_DESTROYED {@link module:audiobridge-plugin~AUDIOBRIDGE_DESTROYED} - * @property {string} EVENT.AUDIOBRIDGE_CONFIGURED {@link module:audiobridge-plugin~AUDIOBRIDGE_CONFIGURED} - * @property {string} EVENT.AUDIOBRIDGE_KICKED - {@link module:audiobridge-plugin~AUDIOBRIDGE_KICKED} - * @property {string} EVENT.AUDIOBRIDGE_PEER_JOINED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_JOINED} - * @property {string} EVENT.AUDIOBRIDGE_PEER_CONFIGURED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_CONFIGURED} - * @property {string} EVENT.AUDIOBRIDGE_PEER_KICKED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_KICKED} - * @property {string} EVENT.AUDIOBRIDGE_PEER_LEAVING {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_LEAVING} - * @property {string} EVENT.AUDIOBRIDGE_TALKING {@link module:audiobridge-plugin~AUDIOBRIDGE_TALKING} - * @property {string} EVENT.AUDIOBRIDGE_PEER_TALKING {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_TALKING} - * @property {string} EVENT.AUDIOBRIDGE_SUSPENDED {@link module:audiobridge-plugin~AUDIOBRIDGE_SUSPENDED} - * @property {string} EVENT.AUDIOBRIDGE_PEER_SUSPENDED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_SUSPENDED} - * @property {string} EVENT.AUDIOBRIDGE_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_RESUMED} - * @property {string} EVENT.AUDIOBRIDGE_PEER_RESUMED {@link module:audiobridge-plugin~AUDIOBRIDGE_PEER_RESUMED} - * @property {string} EVENT.AUDIOBRIDGE_ROOM_MUTED {@link module:audiobridge-plugin~AUDIOBRIDGE_ROOM_MUTED} - * @property {string} EVENT.AUDIOBRIDGE_ANNOUNCEMENT_STARTED {@link module:audiobridge-plugin~AUDIOBRIDGE_ANNOUNCEMENT_STARTED} - * @property {string} EVENT.AUDIOBRIDGE_ANNOUNCEMENT_STOPPED {@link module:audiobridge-plugin~AUDIOBRIDGE_ANNOUNCEMENT_STOPPED} - * @property {string} EVENT.AUDIOBRIDGE_ERROR {@link module:audiobridge-plugin~AUDIOBRIDGE_ERROR} + * @property {Object} EVENT - The events emitted by the plugin + * @property {string} EVENT.AUDIOBRIDGE_DESTROYED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_DESTROYED AUDIOBRIDGE_DESTROYED} + * @property {string} EVENT.AUDIOBRIDGE_CONFIGURED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_CONFIGURED AUDIOBRIDGE_CONFIGURED} + * @property {string} EVENT.AUDIOBRIDGE_KICKED - {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_KICKED AUDIOBRIDGE_KICKED} + * @property {string} EVENT.AUDIOBRIDGE_PEER_JOINED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_JOINED AUDIOBRIDGE_PEER_JOINED} + * @property {string} EVENT.AUDIOBRIDGE_PEER_CONFIGURED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_CONFIGURED AUDIOBRIDGE_PEER_CONFIGURED} + * @property {string} EVENT.AUDIOBRIDGE_PEER_KICKED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_KICKED AUDIOBRIDGE_PEER_KICKED} + * @property {string} EVENT.AUDIOBRIDGE_PEER_LEAVING {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_LEAVING AUDIOBRIDGE_PEER_LEAVING} + * @property {string} EVENT.AUDIOBRIDGE_TALKING {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_TALKING AUDIOBRIDGE_TALKING} + * @property {string} EVENT.AUDIOBRIDGE_PEER_TALKING {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_TALKING AUDIOBRIDGE_PEER_TALKING} + * @property {string} EVENT.AUDIOBRIDGE_SUSPENDED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_SUSPENDED AUDIOBRIDGE_SUSPENDED} + * @property {string} EVENT.AUDIOBRIDGE_PEER_SUSPENDED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_SUSPENDED AUDIOBRIDGE_PEER_SUSPENDED} + * @property {string} EVENT.AUDIOBRIDGE_RESUMED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_RESUMED AUDIOBRIDGE_RESUMED} + * @property {string} EVENT.AUDIOBRIDGE_PEER_RESUMED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_RESUMED AUDIOBRIDGE_PEER_RESUMED} + * @property {string} EVENT.AUDIOBRIDGE_ROOM_MUTED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ROOM_MUTED AUDIOBRIDGE_ROOM_MUTED} + * @property {string} EVENT.AUDIOBRIDGE_ANNOUNCEMENT_STARTED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ANNOUNCEMENT_STARTED AUDIOBRIDGE_ANNOUNCEMENT_STARTED} + * @property {string} EVENT.AUDIOBRIDGE_ANNOUNCEMENT_STOPPED {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ANNOUNCEMENT_STOPPED AUDIOBRIDGE_ANNOUNCEMENT_STOPPED} + * @property {string} EVENT.AUDIOBRIDGE_ERROR {@link module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ERROR AUDIOBRIDGE_ERROR} */ export default { id: PLUGIN_ID, @@ -1479,7 +1480,8 @@ export default { * The audiobridge room has been destroyed. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_DESTROYED - * @type {module:audiobridge-plugin~AUDIOBRIDGE_EVENT_DESTROYED} + * @type {Object} + * @property {number|string} room */ AUDIOBRIDGE_DESTROYED: PLUGIN_EVENT.DESTROYED, @@ -1487,7 +1489,7 @@ export default { * The current user has been configured. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_CONFIGURED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed * @property {string} [display] @@ -1500,7 +1502,7 @@ export default { * The current user has been kicked out. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_KICKED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed */ @@ -1510,7 +1512,7 @@ export default { * A new participant joined. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_JOINED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed * @property {string} [display] @@ -1523,7 +1525,7 @@ export default { * A participant has been configured. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_CONFIGURED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed * @property {string} [display] @@ -1536,7 +1538,7 @@ export default { * A participant has been kicked out. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_KICKED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed */ @@ -1546,7 +1548,7 @@ export default { * A participant is leaving. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_LEAVING - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed */ @@ -1556,7 +1558,7 @@ export default { * Notify if the current user is talking. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_TALKING - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed * @property {boolean} talking @@ -1567,7 +1569,7 @@ export default { * Notify if a participant is talking. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_TALKING - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed * @property {boolean} talking @@ -1578,7 +1580,7 @@ export default { * The current user has been suspended. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_SUSPENDED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed */ @@ -1587,7 +1589,7 @@ export default { * Notify if a participant has been suspended. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_SUSPENDED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed * @property {string} display @@ -1598,7 +1600,7 @@ export default { * The current user has been resumed. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_RESUMED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed */ @@ -1608,7 +1610,7 @@ export default { * Notify if a participant has been resumed. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_RESUMED - * @type {object} + * @type {Object} * @property {number|string} room * @property {number|string} feed * @property {string} display @@ -1619,7 +1621,7 @@ export default { * The room has been muted or not. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ROOM_MUTED - * @type {object} + * @type {Object} * @property {number|string} room * @property {boolean} muted */ @@ -1629,7 +1631,7 @@ export default { * The announcement has been started. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ANNOUNCEMENT_STARTED - * @type {object} + * @type {Object} * @property {number|string} room * @property {string} file_id */ @@ -1639,7 +1641,7 @@ export default { * The announcement has been stopped. * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ANNOUNCEMENT_STOPPED - * @type {object} + * @type {Object} * @property {number|string} room * @property {string} file_id */ diff --git a/src/plugins/echotest-plugin.js b/src/plugins/echotest-plugin.js index f67246c..97b8e57 100644 --- a/src/plugins/echotest-plugin.js +++ b/src/plugins/echotest-plugin.js @@ -26,6 +26,7 @@ const PLUGIN_EVENT = { * Moreover it defines some methods to support EchoTest operations.
* * @hideconstructor + * @extends module:handle~Handle */ class EchoTestHandle extends Handle { /** @@ -42,8 +43,8 @@ class EchoTestHandle extends Handle { * The custom "handleMessage" needed for handling EchoTest messages. * * @private - * @param {object} janus_message - * @returns {object} A falsy value for unhandled events, a truthy value for handled events + * @param {Object} janus_message + * @returns {Object} A falsy value for unhandled events, a truthy value for handled events */ handleMessage(janus_message) { const { plugindata, transaction } = janus_message; @@ -105,7 +106,7 @@ class EchoTestHandle extends Handle { /** * Start/update an echotest session. * - * @param {object} params + * @param {Object} params * @param {boolean} [params.audio] - True to request audio in this session * @param {boolean} [params.video] - True to request video in this session * @param {RTCSessionDescription} [params.jsep=null] - The JSEP offer @@ -144,11 +145,11 @@ class EchoTestHandle extends Handle { * {@link https://janus.conf.meetecho.com/docs/echotest.html} * * @private - * @typedef {object} EchoTestData + * @typedef {Object} EchoTestData */ /** - * @typedef {object} ECHOTEST_EVENT_RESULT + * @typedef {Object} ECHOTEST_EVENT_RESULT * @property {string} result - The result status (ok, done ...) * @property {RTCSessionDescription} [jsep] - The answer from Janus */ @@ -156,13 +157,13 @@ class EchoTestHandle extends Handle { /** * The exported plugin descriptor. * - * @type {object} + * @type {Object} * @property {string} id - The plugin identifier used when attaching to Janus * @property {module:echotest-plugin~EchoTestHandle} Handle - The custom class implementing the plugin - * @property {object} EVENT - The events emitted by the plugin - * @property {string} EVENT.ECHOTEST_RESULT {@link module:echotest-plugin~ECHOTEST_RESULT} - * @property {string} EVENT.ECHOTEST_SLOWLINK {@link module:echotest-plugin~ECHOTEST_SLOWLINK} - * @property {string} EVENT.ECHOTEST_ERROR {@link module:echotest-plugin~ECHOTEST_ERROR} + * @property {Object} EVENT - The events emitted by the plugin + * @property {string} EVENT.ECHOTEST_RESULT {@link module:echotest-plugin~EchoTestHandle#event:ECHOTEST_RESULT ECHOTEST_RESULT} + * @property {string} EVENT.ECHOTEST_SLOWLINK {@link module:echotest-plugin~EchoTestHandle#event:ECHOTEST_SLOWLINK ECHOTEST_SLOWLINK} + * @property {string} EVENT.ECHOTEST_ERROR {@link module:echotest-plugin~EchoTestHandle#event:ECHOTEST_ERROR ECHOTEST_ERROR} */ export default { id: PLUGIN_ID, @@ -170,13 +171,15 @@ export default { EVENT: { /** * @event module:echotest-plugin~EchoTestHandle#event:ECHOTEST_RESULT - * @type {module:echotest-plugin~ECHOTEST_EVENT_RESULT} + * @type {Object} + * @property {string} result + * @property {RTCSessionDescription} [jsep] */ ECHOTEST_RESULT: PLUGIN_EVENT.RESULT, /** * @event module:echotest-plugin~EchoTestHandle#event:ECHOTEST_SLOWLINK - * @type {object} + * @type {Object} * @property {number} bitrate */ ECHOTEST_SLOWLINK: PLUGIN_EVENT.SLOWLINK, diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index 59fcac2..b316cb9 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -50,6 +50,7 @@ const PLUGIN_EVENT = { * Moreover it defines many methods to support Streaming operations.
* * @hideconstructor + * @extends module:handle~Handle */ class StreamingHandle extends Handle { /** @@ -72,8 +73,8 @@ class StreamingHandle extends Handle { * The custom "handleMessage" needed for handling Streamiing messages. * * @private - * @param {object} janus_message - * @returns {object} A falsy value for unhandled events, a truthy value for handled events + * @param {Object} janus_message + * @returns {Object} A falsy value for unhandled events, a truthy value for handled events */ handleMessage(janus_message) { const { plugindata, transaction } = janus_message; @@ -202,7 +203,7 @@ class StreamingHandle extends Handle { /** * Subscribe to a mountpoint. * - * @param {object} params + * @param {Object} params * @param {number|string} params.id - The mp id * @param {string} [params.pin] - The optional mp pin * @param {boolean} [params.audio] - True to request audio @@ -244,7 +245,7 @@ class StreamingHandle extends Handle { /** * Start a mountpoint stream. * - * @param {object} params + * @param {Object} params * @param {RTCSessionDescription} params.jsep * @param {boolean} [params.e2ee] * @returns {Promise} @@ -307,7 +308,7 @@ class StreamingHandle extends Handle { /** * Switch to another mountpoint. * - * @param {object} params + * @param {Object} params * @param {number|string} params.id - The mp id to switch to * @returns {Promise} */ @@ -331,7 +332,7 @@ class StreamingHandle extends Handle { /** * Configure an active stream. * - * @param {object} params + * @param {Object} params * @param {boolean} [params.audio] - Enable/disable audio * @param {boolean} [params.video] - Enable/disable video * @param {boolean} [params.data] - Enable/disable data @@ -372,7 +373,7 @@ class StreamingHandle extends Handle { /** * List all the available mountpoints. * - * @param {object} params + * @param {Object} params * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ @@ -393,7 +394,7 @@ class StreamingHandle extends Handle { /** * Get mountpoint info. * - * @param {object} params + * @param {Object} params * @param {number|string} params.id * @param {string} [params.secret] * @returns {Promise} @@ -416,7 +417,7 @@ class StreamingHandle extends Handle { /** * Start recording on a mountpoint * - * @param {object} params + * @param {Object} params * @param {number|string} params.id * @param {string} [params.audio] - The filename for audio * @param {string} [params.video] - The filename for video @@ -453,7 +454,7 @@ class StreamingHandle extends Handle { /** * Stop recording on a mountpoint. * - * @param {object} params + * @param {Object} params * @param {number|string} params.id * @param {boolean} [params.audio=true] - True to stop recording of audio * @param {boolean} [params.video=true] - True to stop recording of video @@ -490,7 +491,7 @@ class StreamingHandle extends Handle { /** * Enable a mountpoint. * - * @param {object} params + * @param {Object} params * @param {number|string} params.id * @param {string} [params.secret] * @returns {Promise} @@ -513,7 +514,7 @@ class StreamingHandle extends Handle { /** * Disable a mountpoint. * - * @param {object} params + * @param {Object} params * @param {number|string} params.id * @param {boolean} [params.stop_recording=true] - True if the user wants to also stop the recording of a disabled moutnpoint * @param {string} [params.secret] @@ -538,7 +539,7 @@ class StreamingHandle extends Handle { /** * Create a RTP live mountpoint. * - * @param {object} params + * @param {Object} params * @param {number|string} [params.id=0] - The id for the new mountpoint (if omitted Janus will pick one) * @param {string} [params.name] - A name for the mp * @param {string} [params.description] - A description for the mp @@ -548,14 +549,14 @@ class StreamingHandle extends Handle { * @param {boolean} [params.permanent=false] - True if Janus must persist the mp on a config file * @param {boolean} [params.is_private=false] - Flag the mp as private * @param {boolean} [params.e2ee=false] - True to set a a mp as end to end encrypted - * @param {object} [params.audio] - The audio descriptor for the mp + * @param {Object} [params.audio] - The audio descriptor for the mp * @param {number} [params.audio.port] - Port used for audio RTP * @param {number} [params.audio.rtcpport] - Port used for audio RTCP * @param {string} [params.audio.mcast] - Multicast address to listen to * @param {number} [params.audio.pt] - Payload type that will be used * @param {string} [params.audio.rtpmap] - rtpmap type that will be used * @param {boolean} [params.audio.skew] - Set skew compensation - * @param {object} [params.video] - The video descriptor for the mp + * @param {Object} [params.video] - The video descriptor for the mp * @param {number} [params.video.port] - Port used for video RTP * @param {number} [params.video.port2] - Port used for video RTP (simulcast layer) * @param {number} [params.video.port3] - Port used for video RTP (simulcast layer) @@ -566,12 +567,12 @@ class StreamingHandle extends Handle { * @param {boolean} [params.video.skew] - Set skew compensation * @param {string} [params.video.fmtp] - fmtp that will be used * @param {boolean} [params.video.buffer] - Enable buffering of the keyframes - * @param {object} [params.data] - The datachannel descriptor for the mp + * @param {Object} [params.data] - The datachannel descriptor for the mp * @param {number} [params.data.port] - Port used for datachannels packets * @param {boolean} [params.data.buffer] - Enable buffering of the datachannels * @param {object[]} [params.media] - [multistream] The media object, each media includes type, mid, port, pt ... * @param {number} [params.threads] - The number of helper threads used in this mp - * @param {object} [params.metadata] - An opaque metadata to add to the mp + * @param {Object} [params.metadata] - An opaque metadata to add to the mp * @param {number} [params.collision] - The stream collision discarding time in number of milliseconds (0=disabled) * @returns {Promise} */ @@ -644,7 +645,7 @@ class StreamingHandle extends Handle { /** * Destroy a mountpoint. * - * @param {object} params + * @param {Object} params * @param {number|string} params.id * @param {boolean} [params.permanent] * @param {string} [params.secret] @@ -673,32 +674,32 @@ class StreamingHandle extends Handle { * {@link https://janus.conf.meetecho.com/docs/streaming.html} * * @private - * @typedef {object} StreamingData + * @typedef {Object} StreamingData */ /** * Success response for streaming requests. * - * @typedef {object} STREAMING_EVENT_OK + * @typedef {Object} STREAMING_EVENT_OK */ /** * Response event for mountpoint info request. * - * @typedef {object} STREAMING_EVENT_INFO + * @typedef {Object} STREAMING_EVENT_INFO */ /** * Response event for mountpoint list request. * - * @typedef {object} STREAMING_EVENT_LIST + * @typedef {Object} STREAMING_EVENT_LIST * @property {object[]} list - The list of mountpoints as returned by Janus */ /** * Response event for mountpoint create request. * - * @typedef {object} STREAMING_EVENT_CREATED + * @typedef {Object} STREAMING_EVENT_CREATED * @property {string} name - The name of the mountpoint * @property {number|string} id - The identifier for the mountpoint * @property {string} description - An optional description @@ -723,14 +724,14 @@ class StreamingHandle extends Handle { /** * Response event for mountpoint destroy request. * - * @typedef {object} STREAMING_EVENT_DESTROYED + * @typedef {Object} STREAMING_EVENT_DESTROYED * @property {number|string} id - The identifier of the dstroyed mountpoint */ /** * A streaming status update event. * - * @typedef {object} STREAMING_EVENT_STATUS + * @typedef {Object} STREAMING_EVENT_STATUS * @property {string} status - The current status of the stream * @property {number|string} [id] - The involved mountpoint identifier * @property {boolean} [restart] - True if the request had it true @@ -741,7 +742,7 @@ class StreamingHandle extends Handle { /** * Response event for mountpoint switch request. * - * @typedef {object} STREAMING_EVENT_SWITCHED + * @typedef {Object} STREAMING_EVENT_SWITCHED * @property {string} switched - The string as returned by Janus * @property {number|string} id - The identifier of the mp that has been switched to */ @@ -749,18 +750,18 @@ class StreamingHandle extends Handle { /** * Response event for configure stream request * - * @typedef {object} STREAMING_EVENT_CONFIGURED + * @typedef {Object} STREAMING_EVENT_CONFIGURED */ /** * The exported plugin descriptor. * - * @type {object} + * @type {Object} * @property {string} id - The plugin identifier used when attaching to Janus * @property {module:streaming-plugin~StreamingHandle} Handle - The custom class implementing the plugin - * @property {object} EVENT - The events emitted by the plugin - * @property {string} EVENT.STREAMING_STATUS {@link module:streaming-plugin~STREAMING_STATUS} - * @property {string} EVENT.STREAMING_ERROR {@link module:streaming-plugin~STREAMING_ERROR} + * @property {Object} EVENT - The events emitted by the plugin + * @property {string} EVENT.STREAMING_STATUS {@link module:streaming-plugin~StreamingHandle#event:STREAMING_STATUS STREAMING_STATUS} + * @property {string} EVENT.STREAMING_ERROR {@link module:streaming-plugin~StreamingHandle#event:STREAMING_ERROR STREAMING_ERROR} */ export default { id: PLUGIN_ID, @@ -770,7 +771,12 @@ export default { * Update of the status for the active stream. * * @event module:streaming-plugin~StreamingHandle#event:STREAMING_STATUS - * @type {module:streaming-plugin~STREAMING_EVENT_STATUS} + * @type {Object} + * @property {string} status + * @property {number|string} [id] + * @property {boolean} [restart] + * @property {boolean} [e2ee] + * @property {RTCSessionDescription} [jsep] */ STREAMING_STATUS: PLUGIN_EVENT.STATUS, diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index 7dd2adb..a9ebd48 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -80,6 +80,7 @@ const PLUGIN_EVENT = { * Moreover it defines many methods to support VideoRoom operations.
* * @hideconstructor + * @extends module:handle~Handle */ class VideoRoomHandle extends Handle { /** @@ -118,8 +119,8 @@ class VideoRoomHandle extends Handle { * The custom "handleMessage" needed for handling VideoRoom messages. * * @private - * @param {object} janus_message - * @returns {object} A falsy value for unhandled events, a truthy value for handled events + * @param {Object} janus_message + * @returns {Object} A falsy value for unhandled events, a truthy value for handled events */ handleMessage(janus_message) { const { plugindata, transaction } = janus_message; @@ -614,7 +615,7 @@ class VideoRoomHandle extends Handle { /** * Join a videoroom as publisher. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room to join to * @param {number|string} [params.feed] - The feed identifier to use, if missing it is picked by Janus * @param {boolean} [params.audio] - True to request audio relaying @@ -662,7 +663,7 @@ class VideoRoomHandle extends Handle { /** * Join and configure videoroom handle as publisher. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room to join to * @param {number|string} [params.feed] - The feed identifier to use, if missing it is picked by Janus * @param {boolean} [params.audio] - True to request audio relaying @@ -739,7 +740,7 @@ class VideoRoomHandle extends Handle { * restart/update flags, while subscribers need to use them to force * the operation. * - * @param {object} params + * @param {Object} params * @param {boolean} [params.audio] - True to request audio relaying * @param {boolean} [params.video] - True to request video relaying * @param {boolean} [params.data] - True to request datachannel relaying @@ -756,7 +757,7 @@ class VideoRoomHandle extends Handle { * @param {number} [params.sc_temporal_layers] - Temporal layers to receive (0-2), in case VP8 simulcasting is enabled (subscribers only) * @param {boolean} [params.e2ee] - True to notify end-to-end encryption for this connection * @param {RTCSessionDescription} [params.jsep] - The JSEP offer (publishers only) - * @param {boolean} [params.keyframe] - True to request a keyframe (publishers only) + * @param {boolean} [params.keyframe] - True to request a keyframe (publishers only) * @returns {Promise} */ async configure({ audio, video, data, bitrate, record, filename, display, restart, update, streams, descriptions, sc_substream_layer, sc_substream_fallback_ms, sc_temporal_layers, e2ee, jsep, keyframe }) { @@ -825,7 +826,7 @@ class VideoRoomHandle extends Handle { * Publish a feed in the room. * Room is detected from the context since a handle must have joined before. * - * @param {object} params + * @param {Object} params * @param {boolean} [params.audio] - True to request audio relaying * @param {boolean} [params.video] - True to request video relaying * @param {boolean} [params.data] - True to request datachannel relaying @@ -913,7 +914,7 @@ class VideoRoomHandle extends Handle { /** * Join a room as subscriber. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room to join * @param {number|string} [params.feed=0] - The feed the user wants to subscribe to * @param {boolean} [params.audio] - Whether or not audio should be relayed @@ -984,7 +985,7 @@ class VideoRoomHandle extends Handle { /** * Start a subscriber stream. * - * @param {object} params + * @param {Object} params * @param {RTCSessionDescription} params.jsep - The JSEP answer * @param {boolean} [params.e2ee] - True to hint an end-to-end encrypted negotiation * @returns {Promise} @@ -1025,7 +1026,7 @@ class VideoRoomHandle extends Handle { /** * Switch to another feed. * - * @param {object} params + * @param {Object} params * @param {number|string} [params.to_feed] - The feed id of the new publisher to switch to * @param {boolean} [params.audio] - True to subscribe to the audio feed * @param {boolean} [params.video] - True to subscribe to the video feed @@ -1080,7 +1081,7 @@ class VideoRoomHandle extends Handle { /** * [multistream] Update a subscription. * - * @param {object} params + * @param {Object} params * @param {object[]} params.subscribe - The array of streams to subscribe * @param {object[]} params.unsubscribe - The array of streams to unsubscribe * @@ -1111,7 +1112,7 @@ class VideoRoomHandle extends Handle { /** * List the participants inside a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where the list is being requested * @param {string} params.secret - The optional secret for the operation * @returns {Promise} @@ -1134,7 +1135,7 @@ class VideoRoomHandle extends Handle { /** * Enable or disable recording for all participants in a room while the conference is in progress. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where the change of recording state is being requested * @param {string} params.secret - The optional secret for the operation * @param {boolean} params.record - True starts recording for all participants in an already running conference, false stops the recording @@ -1161,7 +1162,7 @@ class VideoRoomHandle extends Handle { /** * Kick a publisher out from a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where the kick is being requested * @param {number|string} params.feed - The identifier of the feed to kick out * @param {string} params.secret - The optional secret for the operation @@ -1189,7 +1190,7 @@ class VideoRoomHandle extends Handle { /** * Check if a room exists. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room to check * @returns {Promise} */ @@ -1210,7 +1211,7 @@ class VideoRoomHandle extends Handle { /** * List all the available rooms. * - * @param {object} params + * @param {Object} params * @param {string} [params.admin_key] - The admin key needed for invoking the API * @returns {Promise} */ @@ -1231,7 +1232,7 @@ class VideoRoomHandle extends Handle { /** * Create a new room. * - * @param {object} params + * @param {Object} params * @param {number|string} [params.room] - The room identifier, if missing picked by janus * @param {string} [params.description] - A textual description of the room * @param {number} [params.max_publishers] - The max number of publishers allowed @@ -1302,7 +1303,7 @@ class VideoRoomHandle extends Handle { /** * Destroy a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room to destroy * @param {boolean} [params.permanent] - True to remove the room from the Janus config file * @param {string} [params.secret] - The secret needed to manage the room @@ -1327,7 +1328,7 @@ class VideoRoomHandle extends Handle { /** * Edit the ACL tokens for a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where to change the acl * @param {"enable"|"disable"|"add"|"remove"} params.action - The action to execute on the acl * @param {string[]} params.list - The list of tokens to execute the action onto @@ -1354,7 +1355,7 @@ class VideoRoomHandle extends Handle { /** * Start a RTP forwarding in a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where to start a forwarder * @param {number|string} params.feed - The feed identifier to forward (must be published) * @param {string} params.host - The target host for the forwarder @@ -1413,7 +1414,7 @@ class VideoRoomHandle extends Handle { /** * Stop a RTP forwarder in a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where to stop a forwarder * @param {number|string} params.feed - The feed identifier for the forwarder to stop (must be published) * @param {number|string} params.stream - The forwarder identifier as returned by the start forward API @@ -1442,7 +1443,7 @@ class VideoRoomHandle extends Handle { /** * List the active forwarders in a room. * - * @param {object} params + * @param {Object} params * @param {number|string} params.room - The room where to list the forwarders * @param {string} [params.secret] - The secret needed for managing the room * @returns {Promise} @@ -1469,13 +1470,13 @@ class VideoRoomHandle extends Handle { * {@link https://janus.conf.meetecho.com/docs/videoroom.html} * * @private - * @typedef {object} VideoRoomData + * @typedef {Object} VideoRoomData */ /** * The response event when a publisher has joined. * - * @typedef {object} VIDEOROOM_EVENT_PUB_JOINED + * @typedef {Object} VIDEOROOM_EVENT_PUB_JOINED * @property {number|string} room - The involved room * @property {number|string} feed - The feed identifier * @property {string} [display] - The dsplay name, if available @@ -1496,7 +1497,7 @@ class VideoRoomHandle extends Handle { /** * The response event when a subscriber has joined. * - * @typedef {object} VIDEOROOM_EVENT_SUB_JOINED + * @typedef {Object} VIDEOROOM_EVENT_SUB_JOINED * @property {number|string} room - The involved room * @property {number|string} [feed] - The published feed identifier * @property {string} [display] - The published feed display name @@ -1506,7 +1507,7 @@ class VideoRoomHandle extends Handle { /** * The response event to a participant list request. * - * @typedef {object} VIDEOROOM_EVENT_PARTICIPANTS_LIST + * @typedef {Object} VIDEOROOM_EVENT_PARTICIPANTS_LIST * @property {number|string} room - The involved room * @property {number|string} feed - The current published feed * @property {object[]} participants - The list of current participants @@ -1519,7 +1520,7 @@ class VideoRoomHandle extends Handle { /** * The response event for room create request. * - * @typedef {object} VIDEOROOM_EVENT_CREATED + * @typedef {Object} VIDEOROOM_EVENT_CREATED * @property {number|string} room - The created room * @property {boolean} permanent - True if the room has been persisted on the Janus configuratin file */ @@ -1527,7 +1528,7 @@ class VideoRoomHandle extends Handle { /** * The response event for room destroy request. * - * @typedef {object} VIDEOROOM_EVENT_DESTROYED + * @typedef {Object} VIDEOROOM_EVENT_DESTROYED * @property {number|string} room - The destroyed room * @property {boolean} permanent - True if the room has been removed from the Janus configuratin file */ @@ -1535,14 +1536,14 @@ class VideoRoomHandle extends Handle { /** * The response event for room exists request. * - * @typedef {object} VIDEOROOM_EVENT_EXISTS + * @typedef {Object} VIDEOROOM_EVENT_EXISTS * @property {number|string} room - The queried room */ /** * Descriptrion of an active RTP forwarder. * - * @typedef {object} RtpForwarder + * @typedef {Object} RtpForwarder * @property {string} host - The target host * @property {number} [audio_port] - The RTP audio target port * @property {number} [audio_rtcp_port] - The RTCP audio target port @@ -1565,7 +1566,7 @@ class VideoRoomHandle extends Handle { /** * The response event for RTP forward start request. * - * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_STARTED + * @typedef {Object} VIDEOROOM_EVENT_RTP_FWD_STARTED * @property {number|string} room - The involved room * @property {RtpForwarder} [forwarder] - The forwarder object * @property {RtpForwarder[]} [forwarders] - [multistream] The array of forwarders @@ -1574,7 +1575,7 @@ class VideoRoomHandle extends Handle { /** * The response event for RTP forward stop request. * - * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_STOPPED + * @typedef {Object} VIDEOROOM_EVENT_RTP_FWD_STOPPED * @property {number|string} room - The involved room * @property {number|string} feed - The feed identifier being forwarded * @property {number} stream - The forwarder identifier @@ -1583,7 +1584,7 @@ class VideoRoomHandle extends Handle { /** * The response event for RTP forwarders list request. * - * @typedef {object} VIDEOROOM_EVENT_RTP_FWD_LIST + * @typedef {Object} VIDEOROOM_EVENT_RTP_FWD_LIST * @property {number|string} room - The involved room * @property {object[]} forwarders - The list of forwarders * @property {number|string} forwarders[].feed - The feed that is being forwarded @@ -1593,21 +1594,21 @@ class VideoRoomHandle extends Handle { /** * The response event for videoroom list request. * - * @typedef {object} VIDEOROOM_EVENT_LIST + * @typedef {Object} VIDEOROOM_EVENT_LIST * @property {object[]} list - The list of the room as returned by Janus */ /** * The response event for ACL tokens edit (allowed) request. * - * @typedef {object} VIDEOROOM_EVENT_ALLOWED + * @typedef {Object} VIDEOROOM_EVENT_ALLOWED * @property {string[]} list - The updated, complete, list of allowed tokens */ /** * The response event for publisher/subscriber configure request. * - * @typedef {object} VIDEOROOM_EVENT_CONFIGURED + * @typedef {Object} VIDEOROOM_EVENT_CONFIGURED * @property {number|string} room - The involved room * @property {number|string} feed - The feed identifier * @property {string} [display] - The display name, if available @@ -1622,7 +1623,7 @@ class VideoRoomHandle extends Handle { /** * The response event for subscriber start request. * - * @typedef {object} VIDEOROOM_EVENT_STARTED + * @typedef {Object} VIDEOROOM_EVENT_STARTED * @property {number|string} room - The involved room * @property {number|string} [feed] - The feed that started * @property {boolean} [e2ee] - True if started stream is e2ee @@ -1632,7 +1633,7 @@ class VideoRoomHandle extends Handle { /** * The response event for subscriber pause request. * - * @typedef {object} VIDEOROOM_EVENT_PAUSED + * @typedef {Object} VIDEOROOM_EVENT_PAUSED * @property {number|string} room - The involved room * @property {number|string} feed - The feed that has been paused * @property {string} paused - A string with the value returned by Janus @@ -1641,7 +1642,7 @@ class VideoRoomHandle extends Handle { /** * The response event for subscriber switch request. * - * @typedef {object} VIDEOROOM_EVENT_SWITCHED + * @typedef {Object} VIDEOROOM_EVENT_SWITCHED * @property {number|string} room - The involved room * @property {number|string} [from_feed] - The feed that has been switched from * @property {number|string} [to_feed] - The feed that has been switched to @@ -1653,7 +1654,7 @@ class VideoRoomHandle extends Handle { /** * The response event for publisher unpublish request. * - * @typedef {object} VIDEOROOM_EVENT_UNPUBLISHED + * @typedef {Object} VIDEOROOM_EVENT_UNPUBLISHED * @property {number|string} room - The involved room * @property {number|string} feed - The feed that unpublished */ @@ -1661,7 +1662,7 @@ class VideoRoomHandle extends Handle { /** * The response event for publiher/subscriber leave request. * - * @typedef {object} VIDEOROOM_EVENT_LEAVING + * @typedef {Object} VIDEOROOM_EVENT_LEAVING * @property {number|string} room - The involved room * @property {number|string} feed - The feed that left * @property {string} [reason] - An optional string with the reason of the leaving @@ -1670,7 +1671,7 @@ class VideoRoomHandle extends Handle { /** * The response event for the kick request. * - * @typedef {object} VIDEOROOM_EVENT_KICKED + * @typedef {Object} VIDEOROOM_EVENT_KICKED * @property {number|string} room - The involved room * @property {number|string} feed - The feed that has been kicked */ @@ -1678,7 +1679,7 @@ class VideoRoomHandle extends Handle { /** * The response event for the recording enabled request. * - * @typedef {object} VIDEOROOM_EVENT_RECORDING_ENABLED_STATE + * @typedef {Object} VIDEOROOM_EVENT_RECORDING_ENABLED_STATE * @property {number|string} room - The involved room * @property {boolean} recording - Whether or not the room recording is now enabled */ @@ -1686,7 +1687,7 @@ class VideoRoomHandle extends Handle { /** * [multistream] The response event for update subscriber request. * - * @typedef {object} VIDEOROOM_EVENT_UPDATED + * @typedef {Object} VIDEOROOM_EVENT_UPDATED * @property {number|string} room - The involved room * @property {RTCSessionDescription} [jsep] - The updated JSEP offer * @property {object[]} streams - List of the updated streams in this subscription @@ -1695,20 +1696,25 @@ class VideoRoomHandle extends Handle { /** * The exported plugin descriptor. * - * @type {object} + * @type {Object} * @property {string} id - The plugin identifier used when attaching to Janus * @property {module:videoroom-plugin~VideoRoomHandle} Handle - The custom class implementing the plugin - * @property {object} EVENT - The events emitted by the plugin - * @property {string} EVENT.VIDEOROOM_PUB_PEER_JOINED {@link module:videoroom-plugin~VIDEOROOM_PUB_PEER_JOINED} - * @property {string} EVENT.VIDEOROOM_PUB_LIST {@link module:videoroom-plugin~VIDEOROOM_PUB_LIST} - * @property {string} EVENT.VIDEOROOM_DESTROYED {@link module:videoroom-plugin~VIDEOROOM_DESTROYED} - * @property {string} EVENT.VIDEOROOM_UNPUBLISHED {@link module:videoroom-plugin~VIDEOROOM_UNPUBLISHED} - * @property {string} EVENT.VIDEOROOM_LEAVING {@link module:videoroom-plugin~VIDEOROOM_LEAVING} - * @property {string} EVENT.VIDEOROOM_DISPLAY {@link module:videoroom-plugin~VIDEOROOM_DISPLAY} - * @property {string} EVENT.VIDEOROOM_KICKED {@link module:videoroom-plugin~VIDEOROOM_KICKED} - * @property {string} EVENT.VIDEOROOM_RECORDING_ENABLED_STATE {@link module:videoroom-plugin~VIDEOROOM_RECORDING_ENABLED_STATE} - * @property {string} EVENT.VIDEOROOM_TALKING {@link module:videoroom-plugin~VIDEOROOM_TALKING} - * @property {string} EVENT.VIDEOROOM_ERROR {@link module:videoroom-plugin~VIDEOROOM_ERROR} + * @property {Object} EVENT - The events emitted by the plugin + * @property {string} EVENT.VIDEOROOM_PUB_PEER_JOINED {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_PUB_PEER_JOINED VIDEOROOM_PUB_PEER_JOINED} + * @property {string} EVENT.VIDEOROOM_PUB_LIST {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_PUB_LIST VIDEOROOM_PUB_LIST} + * @property {string} EVENT.VIDEOROOM_DESTROYED {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DESTROYED VIDEOROOM_DESTROYED} + * @property {string} EVENT.VIDEOROOM_UNPUBLISHED {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UNPUBLISHED VIDEOROOM_UNPUBLISHED} + * @property {string} EVENT.VIDEOROOM_LEAVING {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_LEAVING VIDEOROOM_LEAVING} + * @property {string} EVENT.VIDEOROOM_DISPLAY {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DISPLAY VIDEOROOM_DISPLAY} + * @property {string} EVENT.VIDEOROOM_CONFIGURED {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_CONFIGURED VIDEOROOM_CONFIGURED} + * @property {string} EVENT.VIDEOROOM_SLOWLINK {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SLOWLINK VIDEOROOM_SLOWLINK} + * @property {string} EVENT.VIDEOROOM_TALKING {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_TALKING VIDEOROOM_TALKING} + * @property {string} EVENT.VIDEOROOM_KICKED {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_KICKED VIDEOROOM_KICKED} + * @property {string} EVENT.VIDEOROOM_RECORDING_ENABLED_STATE {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_RECORDING_ENABLED_STATE VIDEOROOM_RECORDING_ENABLED_STATE} + * @property {string} EVENT.VIDEOROOM_SC_SUBSTREAM_LAYER {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_SUBSTREAM_LAYER VIDEOROOM_SC_SUBSTREAM_LAYER} + * @property {string} EVENT.VIDEOROOM_SC_TEMPORAL_LAYERS {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_TEMPORAL_LAYERS VIDEOROOM_SC_TEMPORAL_LAYERS} + * @property {string} EVENT.VIDEOROOM_UPDATED {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UPDATED VIDEOROOM_UPDATED} + * @property {string} EVENT.VIDEOROOM_ERROR {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_ERROR VIDEOROOM_ERROR} */ export default { id: PLUGIN_ID, @@ -1718,7 +1724,7 @@ export default { * A peer has joined theh room (notify-joining). * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_PUB_PEER_JOINED - * @type {object} + * @type {Object} * @property {number|string} room - The involved room * @property {number|string} feed - The feed identifier that joined * @property {string} display - The display name of the peer @@ -1729,7 +1735,7 @@ export default { * Active publishers list updated. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_PUB_LIST - * @type {object} + * @type {Object} * @property {number|string} room - The involved room * @property {number|string} feed - The current feed identifier * @property {object[]} publishers - List of the new publishers @@ -1747,7 +1753,9 @@ export default { * The videoroom has been destroyed. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DESTROYED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_DESTROYED} + * @type {Object} + * @property {number|string} room - The destroyed room + * @property {boolean} permanent - True if the room has been removed from the Janus configuratin file */ VIDEOROOM_DESTROYED: PLUGIN_EVENT.DESTROYED, @@ -1755,7 +1763,9 @@ export default { * A feed has been unpublished. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UNPUBLISHED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_UNPUBLISHED} + * @type {Object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that unpublished */ VIDEOROOM_UNPUBLISHED: PLUGIN_EVENT.UNPUBLISHED, @@ -1763,7 +1773,10 @@ export default { * A peer has left the room. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_LEAVING - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_LEAVING} + * @type {Object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that left + * @property {string} [reason] - An optional string with the reason of the leaving */ VIDEOROOM_LEAVING: PLUGIN_EVENT.LEAVING, @@ -1771,7 +1784,7 @@ export default { * A participant has changed the display name. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_DISPLAY - * @type {object} + * @type {Object} * @property {number|string} room - The involved room * @property {number|string} feed - The feed of the peer that change display name * @property {string} display - The new display name of the peer @@ -1782,7 +1795,16 @@ export default { * A handle received a configured event. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_CONFIGURED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_CONFIGURED} + * @type {Object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed identifier + * @property {string} [display] - The display name, if available + * @property {boolean} [restart] - True if the request had it true + * @property {boolean} [update] - True if the request had it true + * @property {string} configured - A string with the value returned by Janus + * @property {object[]} [streams] - [multistream] Streams description as returned by Janus + * @property {boolean} [e2ee] - True if the stream is end-to-end encrypted + * @property {RTCSessionDescription} [jsep] - The JSEP answer */ VIDEOROOM_CONFIGURED: PLUGIN_EVENT.CONFIGURED, @@ -1790,7 +1812,7 @@ export default { * A handle received a slow link notification. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SLOWLINK - * @type {object} + * @type {Object} * @property {number|string} room - The involved room * @property {number|string} feed - The feed of the peer that change display name * @property {number} bitrate - The current bitrate cap for the participant @@ -1801,7 +1823,7 @@ export default { * Notify if the current user is talking. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_TALKING - * @type {object} + * @type {Object} * @property {number|string} room - The involved room * @property {number|string} feed - The feed of the peer this talking notification refers to * @property {boolean} talking - True if the participant is talking @@ -1813,7 +1835,9 @@ export default { * A feed has been kicked out. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_KICKED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_KICKED} + * @type {Object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that has been kicked */ VIDEOROOM_KICKED: PLUGIN_EVENT.KICKED, @@ -1821,7 +1845,9 @@ export default { * Conference recording has been enabled or disabled. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_RECORDING_ENABLED_STATE - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_RECORDING_ENABLED_STATE} + * @type {Object} + * @property {number|string} room - The involved room + * @property {boolean} recording - Whether or not the room recording is now enabled */ VIDEOROOM_RECORDING_ENABLED_STATE: PLUGIN_EVENT.RECORDING_ENABLED_STATE, @@ -1829,7 +1855,7 @@ export default { * A switch to a different simulcast substream has been completed. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_SUBSTREAM_LAYER - * @type {object} + * @type {Object} * @property {number|string} room - The involved room * @property {number|string} feed - The feed of the peer this notification refers to * @property {number} sc_substream_layer - The new simuclast substream layer relayed @@ -1840,7 +1866,7 @@ export default { * A switch to a different number of simulcast temporal layers has been completed. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_TEMPORAL_LAYERS - * @type {object} + * @type {Object} * @property {number|string} room - The involved room * @property {number|string} feed - The feed of the peer this switch notification refers to * @property {number} sc_temporal_layers - The new number of simuclast teporal layers relayed @@ -1851,7 +1877,10 @@ export default { * A multistream subscription has been updated. * * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_UPDATED - * @type {module:videoroom-plugin~VIDEOROOM_EVENT_UPDATED} + * @type {Object} + * @property {number|string} room - The involved room + * @property {RTCSessionDescription} [jsep] - The updated JSEP offer + * @property {object[]} streams - List of the updated streams in this subscription */ VIDEOROOM_UPDATED: PLUGIN_EVENT.UPDATED, diff --git a/src/protocol.js b/src/protocol.js index 4e328ce..8e75582 100644 --- a/src/protocol.js +++ b/src/protocol.js @@ -13,7 +13,6 @@ * * Some helper methods related to the protocols are defined here too. * @module protocol - * @private */ /** @@ -77,6 +76,20 @@ export const JANUS = { }, }; +/** + * @typedef {Object} JanodeCoreEvents + * @property {string} CONNECTION_CLOSED - {@link module:connection~Connection#event:CONNECTION_CLOSED CONNECTION_CLOSED} + * @property {string} SESSION_DESTROYED - {@link module:session~Session#event:SESSION_DESTROYED SESSION_DESTROYED} + * @property {string} HANDLE_DETACHED - {@link module:handle~Handle#event:HANDLE_DETACHED HANDLE_DETACHED} + * @property {string} HANDLE_ICE_FAILED - {@link module:handle~Handle#event:HANDLE_ICE_FAILED HANDLE_ICE_FAILED} + * @property {string} HANDLE_HANGUP - {@link module:handle~Handle#event:HANDLE_HANGUP HANDLE_HANGUP} + * @property {string} HANDLE_MEDIA - {@link module:handle~Handle#event:HANDLE_MEDIA HANDLE_MEDIA} + * @property {string} HANDLE_WEBRTCUP - {@link module:handle~Handle#event:HANDLE_WEBRTCUP HANDLE_WEBRTCUP} + * @property {string} HANDLE_SLOWLINK - {@link module:handle~Handle#event:HANDLE_SLOWLINK HANDLE_SLOWLINK} + * @property {string} HANDLE_TRICKLE - {@link module:handle~Handle#event:HANDLE_TRICKLE HANDLE_TRICKLE} + * @property {string} CONNECTION_ERROR - {@link module:connection~Connection#event:CONNECTION_ERROR CONNECTION_ERROR} + */ + /** * Janode protocol constants * @@ -85,6 +98,8 @@ export const JANUS = { export const JANODE = { /** * Janode core events. + * + * @type {JanodeCoreEvents} */ EVENT: { CONNECTION_CLOSED: 'connection_closed', @@ -104,7 +119,7 @@ export const JANODE = { * Check if a message from Janus is a definitive response. * * @private - * @param {object} data - The data from Janus + * @param {Object} data - The data from Janus * @returns {boolean} True if the check succeeds */ export const isResponseData = data => { @@ -118,7 +133,7 @@ export const isResponseData = data => { * Check if a message from Janus is an event. * * @private - * @param {object} data - The data from Janus + * @param {Object} data - The data from Janus * @returns {boolean} True if the check succeeds */ export const isEventData = data => { @@ -132,7 +147,7 @@ export const isEventData = data => { * Check if a message from Janus is an error. * * @private - * @param {object} data - The data from Janus + * @param {Object} data - The data from Janus * @returns {boolean} True if the check succeeds */ export const isErrorData = data => { @@ -146,7 +161,7 @@ export const isErrorData = data => { * Check if a message from Janus is a timeout notification. * * @private - * @param {object} data - The data from Janus + * @param {Object} data - The data from Janus * @returns {boolean} True if the check succeeds */ export const isTimeoutData = data => { @@ -160,7 +175,7 @@ export const isTimeoutData = data => { * Check if a message from Janus is an ack. * * @private - * @param {object} data - The data from Janus + * @param {Object} data - The data from Janus * @returns {boolean} True if the check succeeds */ export const isAckData = data => { diff --git a/src/session.js b/src/session.js index f908462..826c775 100644 --- a/src/session.js +++ b/src/session.js @@ -3,7 +3,7 @@ /** * This module contains the Session class definition. * @module session - * @access private + * @private */ import { EventEmitter } from 'events'; @@ -38,7 +38,7 @@ class Session extends EventEmitter { * The transaction manager used by this session. * * @private - * @type {TransactionManager} + * @type {module:tmanager~TransactionManager} */ this._tm = connection._tm; @@ -145,7 +145,6 @@ class Session extends EventEmitter { * The session has been destroyed. * * @event module:session~Session#event:SESSION_DESTROYED - * @type {object} * @property {number} id - The session identifier */ this.emit(JANODE.EVENT.SESSION_DESTROYED, { id: this.id }); @@ -240,7 +239,7 @@ class Session extends EventEmitter { * the transaction will be closed. * * @private - * @param {object} janus_message + * @param {Object} janus_message */ _handleMessage(janus_message) { const { sender, janus, transaction } = janus_message; @@ -325,7 +324,7 @@ class Session extends EventEmitter { * Decorate request with session id and transaction (if missing). * * @private - * @param {object} request + * @param {Object} request */ _decorateRequest(request) { request.transaction = request.transaction || getNumericID(); @@ -335,8 +334,8 @@ class Session extends EventEmitter { /** * Send a request from this session. * - * @param {object} request - * @returns {Promise} A promise resolving with the response + * @param {Object} request + * @returns {Promise} A promise resolving with the response */ async sendRequest(request) { /* Input check */ diff --git a/src/tmanager.js b/src/tmanager.js index a084fd7..04ffb19 100644 --- a/src/tmanager.js +++ b/src/tmanager.js @@ -10,9 +10,9 @@ /** * An object describing a pending transaction stored in the manager. * - * @typedef {object} PendingTransaction + * @typedef {Object} PendingTransaction * @property {string} id - The transaction identifier - * @property {object} owner - A reference to the object that created the transaction + * @property {Object} owner - A reference to the object that created the transaction * @property {string} request - The janus request for the pending transaction * @property {function} done - The success callback * @property {function} error - The error callback @@ -130,7 +130,7 @@ class TransactionManager { * Create a new transaction if id does not exist in the table and add it to the TM. * * @param {string} id - The transaction identifier - * @param {object} owner - A reference to the object that created the transaction + * @param {Object} owner - A reference to the object that created the transaction * @param {string} request - The janus request for the pending transaction * @param {function} done - The success callback * @param {function} error - The error callback @@ -155,8 +155,8 @@ class TransactionManager { * The closed transaction will be removed from the internal table and the error cb will be invoked with the error string. * * @param {string} id - The transaction identifier - * @param {object} owner - A reference to the transaction owner - * @param {object} error - The error object + * @param {Object} owner - A reference to the transaction owner + * @param {Error} error - The error object * @returns {PendingTransaction|void} The closed transaction, or nothing if the id does not exist or the owner does not match */ closeTransactionWithError(id, owner, error) { @@ -174,8 +174,8 @@ class TransactionManager { * If an owner is specified only the owner's transaction will be closed. * The closed transactions will be removed from the internal table. * - * @param {object} [owner] - A reference to the transaction owner - * @param {object} error - The error object + * @param {Object} [owner] - A reference to the transaction owner + * @param {Error} error - The error object */ closeAllTransactionsWithError(owner, error) { for (const [_, pendingTx] of this.transactions) { @@ -189,8 +189,8 @@ class TransactionManager { * The closed transaction will be removed from the internal table and the success cb will be invoked with the specified data. * * @param {string} id - The transaction identifier - * @param {object} owner - A reference to the transaction owner - * @param {*} data - The success callback data + * @param {Object} owner - A reference to the transaction owner + * @param {Object} data - The success callback data * @returns {PendingTransaction|void} The closed transaction, or nothing if the id does not exist or the owner does not match */ closeTransactionWithSuccess(id, owner, data) { diff --git a/src/transport-unix.js b/src/transport-unix.js index 86c89bc..eaaf83c 100644 --- a/src/transport-unix.js +++ b/src/transport-unix.js @@ -3,7 +3,7 @@ /** * This module contains the Unix Sockets transport implementation. * @module transport-unix - * @access private + * @private */ import { Buffer } from 'buffer'; @@ -16,6 +16,11 @@ import Logger from './utils/logger.js'; const LOG_NS = '[transport-unix.js]'; import { delayOp } from './utils/utils.js'; +/** + * @typedef {Object} UnixDgramSocket + * @link https://www.npmjs.com/package/unix-dgram#api + */ + /** * Class representing a connection through Unix dgram sockets transport.
* @@ -42,7 +47,8 @@ class TransportUnix { /** * The internal Unix Socket. * - * @type {module:unix-dgram~Socket} + * @type {UnixDgramSocket} + * @link https://www.npmjs.com/package/unix-dgram#api */ this._socket = null; @@ -171,7 +177,7 @@ class TransportUnix { * In case of error retry the connection with another address from the available pool. * If maximum number of attempts is reached, throws an error. * - * @returns {module:unix-dgram~Socket} The unix socket + * @returns {UnixDgramSocket} The unix socket */ async _attemptOpen() { /* Reset status at every attempt */ @@ -291,8 +297,8 @@ class TransportUnix { * Send a request from this connection. * It is called from the parent connection. * - * @param {object} request - The request to be sent - * @returns {Promise} A promise resolving with a response from Janus + * @param {Object} request - The request to be sent + * @returns {Promise} A promise resolving with a response from Janus */ async send(request) { /* Check connection status */ diff --git a/src/transport-ws.js b/src/transport-ws.js index 4f41dc2..2ed9447 100644 --- a/src/transport-ws.js +++ b/src/transport-ws.js @@ -3,7 +3,7 @@ /** * This module contains the WebSocket transport implementation. * @module transport-ws - * @access private + * @private */ /* Isomorphic implementation of WebSocket */ @@ -94,7 +94,7 @@ class TransportWs { /** * The task of the peridic ws ping. * - * @type {*} + * @type {Object} */ this._ping_task = null; @@ -378,8 +378,8 @@ class TransportWs { * Wraps with a promise the standard WebSocket API "send". * It is called from the parent connection. * - * @param {object} request - The request to be sent - * @returns {Promise} A promise resolving with a response from Janus + * @param {Object} request - The request to be sent + * @returns {Promise} A promise resolving with a response from Janus */ async send(request) { /* Check connection status */ diff --git a/src/utils/logger.js b/src/utils/logger.js index 9818b65..027a19a 100644 --- a/src/utils/logger.js +++ b/src/utils/logger.js @@ -7,7 +7,7 @@ * * Default logging level is "info". * @module logger - * @access private + * @private */ import { getCliArgument } from './utils.js'; @@ -19,24 +19,39 @@ const LEVELS_IDX = LEVELS.reduce((obj, lvl, idx) => { }, {}); const DEFAULT_LEVEL = 'info'; -let log_verbosity = getCliArgument('janode-log', 'string', DEFAULT_LEVEL); - -const printout = (msg_verbosity, console_fn, ...args) => { - if (LEVELS_IDX[msg_verbosity] > LEVELS_IDX[log_verbosity]) return; - const ts = (new Date()).toISOString(); - const prefix = `${ts} - ${msg_verbosity.toUpperCase().padEnd(8, ' ')}:`; - if (args.length === 1 && typeof args[0] === 'function') { - const msg = (args[0])(); - console_fn(prefix, msg); - } - else - console_fn(prefix, ...args); -}; /** - * The logger used by Janode. + * Class representing a Janode logger.
+ * + * Users are not expected to create Logger instances, but insted use the Janode.Logger instance.
+ * + * @hideconstructor */ -const Logger = { +class Logger { + constructor(lvl = DEFAULT_LEVEL) { + /** + * The current verbosity level of the logger. + * @type {string} + * @private + */ + this._log_verbosity = this.setLevel(lvl); + } + + /** + * @private + */ + _printout(msg_verbosity, console_fn, ...args) { + if (LEVELS_IDX[msg_verbosity] > LEVELS_IDX[this._log_verbosity]) return; + const ts = (new Date()).toISOString(); + const prefix = `${ts} - ${msg_verbosity.toUpperCase().padEnd(8, ' ')}:`; + if (args.length === 1 && typeof args[0] === 'function') { + const msg = (args[0])(); + console_fn(prefix, msg); + } + else + console_fn(prefix, ...args); + } + /** * Debug logging. * It is a wrapper for `console.debug()`. @@ -44,7 +59,9 @@ const Logger = { * @function * @param {...any} args */ - debug: (...args) => printout('debug', console.debug, ...args), + debug(...args) { + this._printout('debug', console.debug, ...args); + } /** * Verbose logging. @@ -53,7 +70,19 @@ const Logger = { * @function * @param {...any} args */ - verbose: (...args) => printout('verbose', console.debug, ...args), + verbose(...args) { + this._printout('verbose', console.debug, ...args); + } + + /** + * Alias for verbose. + * + * @function + * @param {...any} args + */ + verb(...args) { + this.verbose(...args); + } /** * Info logging (default). @@ -62,7 +91,9 @@ const Logger = { * @function * @param {...any} args */ - info: (...args) => printout('info', console.info, ...args), + info(...args) { + this._printout('info', console.info, ...args); + } /** * Warning logging. @@ -71,7 +102,19 @@ const Logger = { * @function * @param {...any} args */ - warning: (...args) => printout('warning', console.warn, ...args), + warning(...args) { + this._printout('warning', console.warn, ...args); + } + + /** + * Alias for warning. + * + * @function + * @param {...any} args + */ + warn(...args) { + this.warning(...args); + } /** * Error logging. @@ -80,7 +123,9 @@ const Logger = { * @function * @param {...any} args */ - error: (...args) => printout('error', console.error, ...args), + error(...args) { + this._printout('error', console.error, ...args); + } /** * Set level of logger. @@ -89,24 +134,32 @@ const Logger = { * @param {"debug"|"verb"|"info"|"warn"|"error"|"none"} lvl * @returns {string} The current level */ - setLevel: (lvl = '') => { + setLevel(lvl = '') { lvl = lvl.toLowerCase(); if (lvl === 'verb') lvl = 'verbose'; if (lvl === 'warn') lvl = 'warning'; if (typeof LEVELS_IDX[lvl] === 'number') { - log_verbosity = lvl; + this._log_verbosity = lvl; } else { - log_verbosity = DEFAULT_LEVEL; + this._log_verbosity = DEFAULT_LEVEL; } - return log_verbosity; + return this._log_verbosity; + } + + /** + * Alias for setLevel. + * + * @function + * @param {"debug"|"verb"|"info"|"warn"|"error"|"none"} lvl + * @returns {string} The current level + */ + setLogLevel(lvl = '') { + return this.setLevel(lvl); } -}; -/* set aliases */ -Logger.verb = Logger.verbose; -Logger.warn = Logger.warning; -Logger.setLogLevel = Logger.setLevel; +} -Logger.setLevel(log_verbosity); +const cli_log_verbosity = getCliArgument('janode-log', 'string', DEFAULT_LEVEL); +const loggerInstance = new Logger(cli_log_verbosity); -export default Logger; \ No newline at end of file +export default loggerInstance; \ No newline at end of file diff --git a/src/utils/utils.js b/src/utils/utils.js index 3c7f7e4..780ba40 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -6,13 +6,6 @@ * @private */ - -/** - * @typedef {object} CircularIterator - * @property {function} nextElem - Advance the iterator and get the new element - * @property {function} currElem - Get the current element without advancing - */ - /** * Generate a random alpha-numeric string with a given length. * @@ -48,6 +41,12 @@ export const getNumericID = (_ => { }; })(); +/** + * @typedef {Object} CircularIterator + * @property {function} nextElem - Advance the iterator and get the new element + * @property {function} currElem - Get the current element without advancing + */ + /** * Generate a circular iterator from an array. * @@ -59,10 +58,13 @@ export const newIterator = list => { const len = l.length; var i = 0; - return { + /** @type {CircularIterator} */ + const iterator = { nextElem: _ => l[i++ % len], currElem: _ => l[i % len], }; + + return iterator; }; /** @@ -81,7 +83,7 @@ export const delayOp = ms => { * Check if a url string contains one of the protocols in a white list. * * @param {string} url_string - The url string to be checked - * @param {Array} admitted - The admitted protocols + * @param {Array} admitted - The admitted protocols * @returns {boolean} True if the check succeeds */ export const checkUrl = (url_string, admitted) => { From c695d74822c5f91cabc5f1182595dff0756cccca Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 29 Apr 2025 18:29:19 +0200 Subject: [PATCH 094/114] eslint: bump version and update config --- eslint.config.js | 14 +++++--- package-lock.json | 89 ++++++++++++++++++++++++++--------------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index f4ff71a..4253287 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,12 +1,18 @@ -import globals from 'globals'; +import { defineConfig } from 'eslint/config'; import js from '@eslint/js'; +import globals from 'globals'; -export default [ +export default defineConfig([ { files: [ + '*.js', 'src/**/*.js', 'examples/**/*.js' ], + plugins: { + js + }, + extends: ['js/recommended'], ignores: [ 'examples/browser/**/*' ], @@ -19,7 +25,7 @@ export default [ } }, rules: { - ...js.configs.recommended.rules, + 'no-trailing-spaces': 'warn', 'no-unused-vars': [ 'warn', { @@ -50,4 +56,4 @@ export default [ 'multiline-comment-style': 1 } } -]; \ No newline at end of file +]); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a153d37..9854db3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -117,13 +117,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", - "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.5", + "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -131,10 +131,20 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz", + "integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -145,9 +155,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { @@ -182,9 +192,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz", + "integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==", "dev": true, "license": "MIT", "engines": { @@ -192,9 +202,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", - "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -202,13 +212,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", - "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.10.0", + "@eslint/core": "^0.13.0", "levn": "^0.4.1" }, "engines": { @@ -268,9 +278,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -698,22 +708,23 @@ } }, "node_modules/eslint": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", - "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz", + "integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.10.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.18.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.25.1", + "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -721,7 +732,7 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -758,9 +769,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -1020,9 +1031,9 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { From 4b2cb05c028ca787cc6a3b5a18be746687687bed Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 30 Apr 2025 10:19:58 +0200 Subject: [PATCH 095/114] eslint: mark deprecated rules --- eslint.config.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 4253287..86c9eda 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -25,7 +25,6 @@ export default defineConfig([ } }, rules: { - 'no-trailing-spaces': 'warn', 'no-unused-vars': [ 'warn', { @@ -37,6 +36,9 @@ export default defineConfig([ 'caughtErrorsIgnorePattern': '^_' } ], + 'no-empty': 'off', + // deprecated rules + 'no-trailing-spaces': 'warn', 'indent': [ 'warn', 2, @@ -52,7 +54,6 @@ export default defineConfig([ 'warn', 'always' ], - 'no-empty': 'off', 'multiline-comment-style': 1 } } From 9a6da0489fc5c665ae4d234d610a9235cc8878fb Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 30 Apr 2025 11:35:28 +0200 Subject: [PATCH 096/114] docs: update --- src/plugins/audiobridge-plugin.js | 88 +++++++++++++++---------------- src/plugins/echotest-plugin.js | 18 +++++-- src/plugins/streaming-plugin.js | 14 ++--- 3 files changed, 64 insertions(+), 56 deletions(-) diff --git a/src/plugins/audiobridge-plugin.js b/src/plugins/audiobridge-plugin.js index c2fb175..b4b9e2e 100644 --- a/src/plugins/audiobridge-plugin.js +++ b/src/plugins/audiobridge-plugin.js @@ -1481,7 +1481,7 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_DESTROYED * @type {Object} - * @property {number|string} room + * @property {number|string} room - The destroyed room identifier */ AUDIOBRIDGE_DESTROYED: PLUGIN_EVENT.DESTROYED, @@ -1490,11 +1490,11 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_CONFIGURED * @type {Object} - * @property {number|string} room - * @property {number|string} feed - * @property {string} [display] - * @property {boolean} [muted] - * @property {boolean} [setup] + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The user feed identifier + * @property {string} [display] - The user display name + * @property {boolean} [muted] - True if the user is muted + * @property {boolean} [setup] - True if the user PeerConnection is up */ AUDIOBRIDGE_CONFIGURED: PLUGIN_EVENT.CONFIGURED, @@ -1503,8 +1503,8 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_KICKED * @type {Object} - * @property {number|string} room - * @property {number|string} feed + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The user feed identifier */ AUDIOBRIDGE_KICKED: PLUGIN_EVENT.KICKED, @@ -1513,11 +1513,11 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_JOINED * @type {Object} - * @property {number|string} room - * @property {number|string} feed - * @property {string} [display] - * @property {boolean} [muted] - * @property {boolean} [setup] + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The joined participant feed identifier + * @property {string} [display] - The joined participant display name + * @property {boolean} [muted] - True if the participant is muted + * @property {boolean} [setup] - True if the participant PeerConnection is up */ AUDIOBRIDGE_PEER_JOINED: PLUGIN_EVENT.PEER_JOINED, @@ -1526,11 +1526,11 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_CONFIGURED * @type {Object} - * @property {number|string} room - * @property {number|string} feed - * @property {string} [display] - * @property {boolean} [muted] - * @property {boolean} [setup] + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The configured participant feed identifier + * @property {string} [display] - The configured participant display name + * @property {boolean} [muted] - True if the participant is muted + * @property {boolean} [setup] - True if the participant PeerConnection is up */ AUDIOBRIDGE_PEER_CONFIGURED: PLUGIN_EVENT.PEER_CONFIGURED, @@ -1539,8 +1539,8 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_KICKED * @type {Object} - * @property {number|string} room - * @property {number|string} feed + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The kicked participant feed identifier */ AUDIOBRIDGE_PEER_KICKED: PLUGIN_EVENT.PEER_KICKED, @@ -1549,8 +1549,8 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_LEAVING * @type {Object} - * @property {number|string} room - * @property {number|string} feed + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The leaving participant feed identifier */ AUDIOBRIDGE_PEER_LEAVING: PLUGIN_EVENT.PEER_LEAVING, @@ -1559,9 +1559,9 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_TALKING * @type {Object} - * @property {number|string} room - * @property {number|string} feed - * @property {boolean} talking + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The user feed identifier + * @property {boolean} talking - True if the user is talking */ AUDIOBRIDGE_TALKING: PLUGIN_EVENT.TALKING, @@ -1570,9 +1570,9 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_TALKING * @type {Object} - * @property {number|string} room - * @property {number|string} feed - * @property {boolean} talking + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The participant feed identifier + * @property {boolean} talking - True if the participant is talking */ AUDIOBRIDGE_PEER_TALKING: PLUGIN_EVENT.PEER_TALKING, @@ -1581,8 +1581,8 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_SUSPENDED * @type {Object} - * @property {number|string} room - * @property {number|string} feed + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The user feed identifier */ AUDIOBRIDGE_SUSPENDED: PLUGIN_EVENT.SUSPENDED, /** @@ -1590,9 +1590,9 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_SUSPENDED * @type {Object} - * @property {number|string} room - * @property {number|string} feed - * @property {string} display + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The participant feed identifier + * @property {string} display - The participant display name */ AUDIOBRIDGE_PEER_SUSPENDED: PLUGIN_EVENT.PEER_SUSPENDED, @@ -1601,8 +1601,8 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_RESUMED * @type {Object} - * @property {number|string} room - * @property {number|string} feed + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The user feed identifier */ AUDIOBRIDGE_RESUMED: PLUGIN_EVENT.RESUMED, @@ -1611,9 +1611,9 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_PEER_RESUMED * @type {Object} - * @property {number|string} room - * @property {number|string} feed - * @property {string} display + * @property {number|string} room - The involved room identifier + * @property {number|string} feed - The participant feed identifier + * @property {string} display - The participant display name */ AUDIOBRIDGE_PEER_RESUMED: PLUGIN_EVENT.PEER_RESUMED, @@ -1622,8 +1622,8 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ROOM_MUTED * @type {Object} - * @property {number|string} room - * @property {boolean} muted + * @property {number|string} room - The involved room identifier + * @property {boolean} muted - True if the room is muted */ AUDIOBRIDGE_ROOM_MUTED: PLUGIN_EVENT.ROOM_MUTED, @@ -1632,8 +1632,8 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ANNOUNCEMENT_STARTED * @type {Object} - * @property {number|string} room - * @property {string} file_id + * @property {number|string} room - The involved room identifier + * @property {string} file_id - Unique string ID of the announcement */ AUDIOBRIDGE_ANNOUNCEMENT_STARTED: PLUGIN_EVENT.ANNOUNCEMENT_STARTED, @@ -1642,8 +1642,8 @@ export default { * * @event module:audiobridge-plugin~AudioBridgeHandle#event:AUDIOBRIDGE_ANNOUNCEMENT_STOPPED * @type {Object} - * @property {number|string} room - * @property {string} file_id + * @property {number|string} room - The involved room identifier + * @property {string} file_id - Unique string ID of the announcement */ AUDIOBRIDGE_ANNOUNCEMENT_STOPPED: PLUGIN_EVENT.ANNOUNCEMENT_STOPPED, diff --git a/src/plugins/echotest-plugin.js b/src/plugins/echotest-plugin.js index 97b8e57..be62d35 100644 --- a/src/plugins/echotest-plugin.js +++ b/src/plugins/echotest-plugin.js @@ -69,7 +69,10 @@ class EchoTestHandle extends Handle { /* EchoTest SlowLink event */ if (event === 'slow_link') { janode_event.event = PLUGIN_EVENT.SLOWLINK; - janode_event.data.bitrate = message_data['current-bitrate']; + janode_event.data.media = message_data.media; + if (typeof message_data['current-bitrate'] !== 'number') { + janode_event.data.bitrate = message_data['current-bitrate']; + } break; } /* EchoTest Result event (ok, done ...) */ @@ -151,7 +154,7 @@ class EchoTestHandle extends Handle { /** * @typedef {Object} ECHOTEST_EVENT_RESULT * @property {string} result - The result status (ok, done ...) - * @property {RTCSessionDescription} [jsep] - The answer from Janus + * @property {RTCSessionDescription} [jsep] - The JSEP answer from Janus */ /** @@ -170,17 +173,22 @@ export default { Handle: EchoTestHandle, EVENT: { /** + * The result event emitted if the session status changes. + * * @event module:echotest-plugin~EchoTestHandle#event:ECHOTEST_RESULT * @type {Object} - * @property {string} result - * @property {RTCSessionDescription} [jsep] + * @property {string} result - The result status (ok, done ...) + * @property {RTCSessionDescription} [jsep] - The JSEP answer from Janus */ ECHOTEST_RESULT: PLUGIN_EVENT.RESULT, /** + * The slowlink event emitted by the plugin. + * * @event module:echotest-plugin~EchoTestHandle#event:ECHOTEST_SLOWLINK * @type {Object} - * @property {number} bitrate + * @property {string} media - The media type (audio, video) + * @property {number} [bitrate] - Current bitrate cap */ ECHOTEST_SLOWLINK: PLUGIN_EVENT.SLOWLINK, diff --git a/src/plugins/streaming-plugin.js b/src/plugins/streaming-plugin.js index b316cb9..d2af62c 100644 --- a/src/plugins/streaming-plugin.js +++ b/src/plugins/streaming-plugin.js @@ -734,9 +734,9 @@ class StreamingHandle extends Handle { * @typedef {Object} STREAMING_EVENT_STATUS * @property {string} status - The current status of the stream * @property {number|string} [id] - The involved mountpoint identifier - * @property {boolean} [restart] - True if the request had it true + * @property {boolean} [restart] - True if the event involves an ICE Restart * @property {boolean} [e2ee] - True if an offered stream is end to end encrypted - * @property {RTCSessionDescription} [jsep] - Optional JSEP offer from Janus + * @property {RTCSessionDescription} [jsep] - Optional JSEP from Janus */ /** @@ -772,11 +772,11 @@ export default { * * @event module:streaming-plugin~StreamingHandle#event:STREAMING_STATUS * @type {Object} - * @property {string} status - * @property {number|string} [id] - * @property {boolean} [restart] - * @property {boolean} [e2ee] - * @property {RTCSessionDescription} [jsep] + * @property {string} status - The current status of the stream + * @property {number|string} [id] - The involved mountpoint identifier + * @property {boolean} [restart] - True if the event involves an ICE Restart + * @property {boolean} [e2ee] - True if an offered stream is end to end encrypted + * @property {RTCSessionDescription} [jsep] - Optional JSEP from Janus */ STREAMING_STATUS: PLUGIN_EVENT.STATUS, From e77f5b5a6d8348634e97aa0c6423db05c442a54a Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 30 Apr 2025 11:45:27 +0200 Subject: [PATCH 097/114] README: add instructions to build documentation --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 884ceea..916222e 100644 --- a/README.md +++ b/README.md @@ -141,3 +141,19 @@ You need to create a bundle with the core library and the needed plugins using a If you get the code from the repo, you can find a `rollup` bundling sample in the `bundle.sh` script under `examples/browser/`. The output will be a `bundle.js` script that defines an `App` global object with the members `Janode` and `EchoTestPlugin`. + +## How to build documentation + +First install the dev dependecies: + +```bash +npm install +``` + +Then use the npm script: + +```bash +npm run build-docs +``` + +Documentation in HTML format will be built under the `docs` folder. \ No newline at end of file From 9f4911f67d13f51ac4d10205eef66b144443b540 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 30 Apr 2025 12:08:05 +0200 Subject: [PATCH 098/114] npm: update dependecies --- package-lock.json | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9854db3..4d49077 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,9 +75,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", + "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", "dev": true, "license": "MIT", "dependencies": { @@ -369,9 +369,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "dev": true, "license": "MIT" }, @@ -408,9 +408,9 @@ "license": "MIT" }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "license": "MIT", "bin": { @@ -934,9 +934,9 @@ } }, "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, "license": "ISC" }, @@ -969,9 +969,9 @@ } }, "node_modules/globals": { - "version": "15.14.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", - "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", "engines": { @@ -1370,9 +1370,9 @@ "license": "MIT" }, "node_modules/nan": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", - "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", + "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", "license": "MIT" }, "node_modules/natural-compare": { @@ -1776,9 +1776,9 @@ } }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "license": "MIT", "engines": { "node": ">=10.0.0" From 15d6b5cf0057d49e7467bf26f41b8708c46a80e0 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 30 Apr 2025 12:27:14 +0200 Subject: [PATCH 099/114] eslint: update config --- eslint.config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 86c9eda..4def16b 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -9,13 +9,13 @@ export default defineConfig([ 'src/**/*.js', 'examples/**/*.js' ], + ignores: [ + 'examples/browser/**/*' + ], plugins: { js }, extends: ['js/recommended'], - ignores: [ - 'examples/browser/**/*' - ], languageOptions: { ecmaVersion: 'latest', sourceType: 'module', From a62cf4f7d25dafaba746811afb2f1c4f52822156 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 21 May 2025 11:45:27 +0200 Subject: [PATCH 100/114] ga: update linting workflow --- .github/workflows/{janode-ci.yml => janode-lint.yml} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename .github/workflows/{janode-ci.yml => janode-lint.yml} (80%) diff --git a/.github/workflows/janode-ci.yml b/.github/workflows/janode-lint.yml similarity index 80% rename from .github/workflows/janode-ci.yml rename to .github/workflows/janode-lint.yml index 19efdca..1abc1ce 100644 --- a/.github/workflows/janode-ci.yml +++ b/.github/workflows/janode-lint.yml @@ -1,10 +1,10 @@ -name: janode-ci +name: Lint Janode code on: push: branches: - master - - test-ci + - test-lint pull_request: branches: - master @@ -17,6 +17,6 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: lts/jod - run: npm ci - run: npm run lint From 95662e87c2a1aaffbeca9581eab7f422985cb35b Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 21 May 2025 13:11:58 +0200 Subject: [PATCH 101/114] ga: rename liniting job --- .github/workflows/janode-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/janode-lint.yml b/.github/workflows/janode-lint.yml index 1abc1ce..c8e46e2 100644 --- a/.github/workflows/janode-lint.yml +++ b/.github/workflows/janode-lint.yml @@ -11,7 +11,7 @@ on: permissions: contents: read jobs: - lint: + build-and-lint: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 From 046b26fbe2154b134463454d70a619a67fd4371b Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 21 May 2025 14:07:51 +0200 Subject: [PATCH 102/114] docs: remove package.json location from build configuration --- jsdoc.json | 1 - 1 file changed, 1 deletion(-) diff --git a/jsdoc.json b/jsdoc.json index 8574aa8..3ca8c63 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -1,7 +1,6 @@ { "opts": { "encoding": "utf8", - "package": "./package.json", "readme": "./README.md", "pedantic": true, "recurse": true, From 328c194534f68d1347ab1f5397a26bb2aa7fd4c7 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 21 May 2025 16:04:53 +0200 Subject: [PATCH 103/114] docs: add GA workwflow for publishing docs on GitHub pages --- .github/workflows/janode-docs.yml | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/janode-docs.yml diff --git a/.github/workflows/janode-docs.yml b/.github/workflows/janode-docs.yml new file mode 100644 index 0000000..cbb2106 --- /dev/null +++ b/.github/workflows/janode-docs.yml @@ -0,0 +1,44 @@ +name: Deploy to GitHub Pages + +on: + push: + branches: + - master + - test-docs +jobs: + build-and-deploy: + permissions: + contents: write + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + runs-on: ubuntu-24.04 + env: + REF_NAME: ${{ github.ref_name }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/jod + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - run: npm ci + - run: npm run build-docs + - name: Add git reference to docs path + run: | + mkdir -p site/docs/$REF_NAME + cp -a docs/. site/docs/$REF_NAME + - name: Update "latest" docs for tagged versions + if: startsWith(github.ref, 'refs/tags/v') + run: | + cp -a docs/. site/docs/latest + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./site + keep_files: true From e225f131ab0bf6649196ae4f1ea9463fa44d1713 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 21 May 2025 16:11:14 +0200 Subject: [PATCH 104/114] readme: add link to online documenation --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 916222e..47e0f9d 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ The supported Janus plugins currently are: The library is available on [npm](https://www.npmjs.com/package/janode) and the source code is on [github](https://github.com/meetecho/janode). +Online documentation can be found at [https://meetecho.github.io/janode](https://meetecho.github.io/janode). + ## Example of usage This is just a pretty simple hello world for the echotest plugin. From 1e436465769def782127274ffa920d3177288619 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 21 May 2025 16:25:02 +0200 Subject: [PATCH 105/114] docs: generate online docs for "v1." tags --- .github/workflows/janode-docs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/janode-docs.yml b/.github/workflows/janode-docs.yml index cbb2106..e0600be 100644 --- a/.github/workflows/janode-docs.yml +++ b/.github/workflows/janode-docs.yml @@ -5,6 +5,8 @@ on: branches: - master - test-docs + tags: + - v1.* jobs: build-and-deploy: permissions: From 4d8fff96156d8f92c3b70a4294c181430335fe85 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 21 May 2025 16:25:22 +0200 Subject: [PATCH 106/114] version: bump to v1.7.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4d49077..517f2b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.7.4", + "version": "1.7.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.7.4", + "version": "1.7.5", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index 3a989ba..1af2d44 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.7.4", + "version": "1.7.5", "type": "module", "keywords": [ "janus", From d753288bcf0ace696d436416d73bfab20ec1f02b Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 26 May 2025 10:21:14 +0200 Subject: [PATCH 107/114] session: set the correct event name for "detached" filtering (fixes #59) --- src/session.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/session.js b/src/session.js index 826c775..3409656 100644 --- a/src/session.js +++ b/src/session.js @@ -250,7 +250,7 @@ class Session extends EventEmitter { const handle = this._handles.get(sender); /* If the handle is missing notifies the user */ if (!handle) { - if (janus === JANUS.EVENT.HANDLE_DETACHED_PLUGIN) { + if (janus === JANUS.EVENT.DETACHED) { /* In case of duplicate "detached" try to not pollute the logs */ Logger.verbose(`${LOG_NS} ${this.name} handle ${sender} not found for incoming message "${janus}"`); return; From a8247c34a8a75c41e216724289d7e212c67be1bf Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 26 May 2025 10:53:56 +0200 Subject: [PATCH 108/114] ga: remove npm caching from docs building workflow --- .github/workflows/janode-docs.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/janode-docs.yml b/.github/workflows/janode-docs.yml index e0600be..1dac577 100644 --- a/.github/workflows/janode-docs.yml +++ b/.github/workflows/janode-docs.yml @@ -21,13 +21,6 @@ jobs: - uses: actions/setup-node@v4 with: node-version: lts/jod - - name: Cache dependencies - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - run: npm ci - run: npm run build-docs - name: Add git reference to docs path From b6d7c0337e32c4a3526b180f38e0bdd2fefb7e98 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Mon, 26 May 2025 11:12:05 +0200 Subject: [PATCH 109/114] sip: add support for SIP plugin (resolves #34) The plugin handles: - register with different mechanisms - simple ingoing and outgoing calls - dtmf tones (SIP INFO and RFC2833) BREAKING CHANGES The support for SIP plugin has two important effects on the Janode core: - Due to the nature of SIP, transactions may now timeout, hence the sendRequest has now a second parameter timeout_ms that defaults to 0 (no timeout). - Transactions will not be automatically closed with success by the core in case of truthy returns from the specialized plugin handleMessage. That is needed to keep transactions open even when handling intermediate events (e.g. INVITE tx should not be closed by a RINGING). As a consequence, plugins must now define every case of successful tx issuing closeTransactionWithSucces whenever it's needed. --- README.md | 3 +- examples/sip/html/index.html | 38 + examples/sip/html/sip-client.js | 397 ++++++++++ examples/sip/package-lock.json | 1092 +++++++++++++++++++++++++++ examples/sip/package.json | 30 + examples/sip/src/config.template.js | 16 + examples/sip/src/index.js | 330 ++++++++ package.json | 1 + src/handle.js | 15 +- src/plugins/sip-plugin.js | 612 +++++++++++++++ src/tmanager.js | 14 +- 11 files changed, 2539 insertions(+), 9 deletions(-) create mode 100644 examples/sip/html/index.html create mode 100644 examples/sip/html/sip-client.js create mode 100644 examples/sip/package-lock.json create mode 100644 examples/sip/package.json create mode 100644 examples/sip/src/config.template.js create mode 100644 examples/sip/src/index.js create mode 100644 src/plugins/sip-plugin.js diff --git a/README.md b/README.md index 47e0f9d..95d1c30 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,13 @@ Internally uses WebSockets or Unix DGRAM Sockets to connect to Janus. The library wraps the Janus core API, the Janus Admin API and some of the most popular plugins APIs. -The supported Janus plugins currently are: +The supported Janus plugins are: - EchoTest - AudioBridge - Streaming - VideoRoom +- SIP The library is available on [npm](https://www.npmjs.com/package/janode) and the source code is on [github](https://github.com/meetecho/janode). diff --git a/examples/sip/html/index.html b/examples/sip/html/index.html new file mode 100644 index 0000000..fdfd87e --- /dev/null +++ b/examples/sip/html/index.html @@ -0,0 +1,38 @@ + + + + + SIP Socket.IO Janode + + + + +
+
+ disconnected +

+

+
+
+
+
+

+ + + +

+

+
+ + +
+
+ + + + + + \ No newline at end of file diff --git a/examples/sip/html/sip-client.js b/examples/sip/html/sip-client.js new file mode 100644 index 0000000..d3bbb03 --- /dev/null +++ b/examples/sip/html/sip-client.js @@ -0,0 +1,397 @@ +/* global io */ + +'use strict'; + +const RTCPeerConnection = (window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection).bind(window); + +let sipPeerConnection; +const localAudio = document.getElementById('localAudio'); +const remoteAudio = document.getElementById('remoteAudio'); + +const connButton = document.getElementById('connect'); +connButton.onclick = () => { + if (socket.connected) + socket.disconnect(); + else + socket.connect(); +}; + +const callButton = document.getElementById('call'); +callButton.onclick = async () => { + if (!socket.connected) return; + const uri = document.getElementById('callee').value; + try { + const offer = await doOffer(); + call(uri, offer); + } catch (error) { + console.log('error during setup/offer', error); + stopAllStreams(); + closePC(); + return; + } +}; + +const hangupButton = document.getElementById('hangup'); +hangupButton.onclick = async () => { + if (!socket.connected) return; + hangup(); +}; + +const declineButton = document.getElementById('decline'); +declineButton.onclick = async () => { + if (!socket.connected) return; + decline(); +}; + +let incoming = null; +const acceptButton = document.getElementById('accept'); +acceptButton.onclick = async () => { + if (!socket.connected || !incoming) return; + const { offer, caller } = incoming; + console.log('accepting call from', caller); + incoming = null; + try { + const answer = await doAnswer(offer); + accept(answer); + } catch (error) { + console.log('error during setup/answer', error); + stopAllStreams(); + closePC(); + return; + } +}; + +function getId() { + return Math.floor(Number.MAX_SAFE_INTEGER * Math.random()); +} + +const scheduleConnection = (function () { + let task = null; + const delay = 5000; + + return (function (secs) { + if (task) return; + const timeout = secs * 1000 || delay; + console.log('scheduled register in ' + timeout + ' ms'); + task = setTimeout(() => { + register(); + task = null; + }, timeout); + }); +})(); + +const socket = io({ + rejectUnauthorized: false, + autoConnect: false, + reconnection: false, +}); + +function register() { + if (!socket.connected) return; + const type = document.getElementById('type').value.length > 0 ? document.getElementById('type').value : null; + const username = document.getElementById('username').value; + const secret = document.getElementById('secret').value; + const proxy = document.getElementById('proxy').value; + socket.emit('register', { + data: { + type, + username, + secret, + proxy, + }, + _id: getId() + }); +} + +function call(uri, offer) { + if (!socket.connected) return; + socket.emit('call', { + data: { + uri, + jsep: offer + }, + _id: getId(), + }); +} + +function accept(answer) { + if (!socket.connected) return; + socket.emit('accept', { + data: { + jsep: answer + }, + _id: getId(), + }); +} + +function hangup() { + if (!socket.connected) return; + socket.emit('hangup', { + data: {}, + _id: getId(), + }); +} + +function decline() { + if (!socket.connected) return; + socket.emit('decline', { + data: {}, + _id: getId(), + }); +} + +function trickle({ candidate }) { + const trickleData = candidate ? { candidate } : {}; + const trickleEvent = candidate ? 'trickle' : 'trickle-complete'; + + socket.emit(trickleEvent, { + data: trickleData, + _id: getId(), + }); +} + +socket.on('registering', ({ data }) => { + console.log('sip registering', data); + document.getElementById('status').innerHTML = 'registering'; +}); + +socket.on('registered', ({ data }) => { + console.log('sip registered', data); + document.getElementById('status').innerHTML = `registered (${data.username})`; +}); + + +socket.on('calling', ({ data }) => { + console.log('sip calling', data); + document.getElementById('status').innerHTML = 'calling'; +}); + +socket.on('ringing', ({ data }) => { + console.log('sip ringing', data); + document.getElementById('status').innerHTML = 'ringing'; +}); + +socket.on('accepted', ({ data }) => { + console.log('sip accepted', data); + if (sipPeerConnection && data.jsep) { + sipPeerConnection.setRemoteDescription(data.jsep) + .then(() => console.log('remote sdp OK')) + .catch(e => console.log('error setting remote sdp', e)); + } + document.getElementById('status').innerHTML = `in call (${data.username})`; +}); + +socket.on('incoming', async ({ data }) => { + console.log('sip incoming', data); + if (data.jsep) { + incoming = { + offer: data.jsep, + caller: data.username, + }; + } + document.getElementById('status').innerHTML = `incoming (${data.username})`; +}); + +socket.on('hangingup', ({ data }) => { + console.log('sip hangingup', data); + document.getElementById('status').innerHTML = 'hangingup'; +}); + +socket.on('hangup', ({ data }) => { + console.log('hangup', data); + document.getElementById('status').innerHTML = 'hangup'; + stopAllStreams(); + closePC(); +}); + +socket.on('declined', ({ data }) => { + console.log('declined', data); + document.getElementById('status').innerHTML = 'declined'; +}); + +socket.on('missed', ({ data }) => { + console.log('missed', data); + document.getElementById('status').innerHTML = 'missed'; +}); + +socket.on('info', ({ data }) => { + console.log('info', data); +}); + +socket.on('dtmf', ({ data }) => { + console.log('dtmf', data); +}); + +socket.on('sip-error', ({ error }) => { + console.log('sip error', error); + document.getElementById('status').innerHTML = 'error: ' + error; + stopAllStreams(); + closePC(); + //socket.disconnect(); +}); + +socket.on('connect', () => { + console.log('socket connected'); + document.getElementById('status').innerHTML = 'connected'; + connButton.innerText = 'DISCONNECT'; + socket.sendBuffer = []; + scheduleConnection(0.1); +}); + +socket.on('disconnect', () => { + console.log('socket disconnected'); + document.getElementById('status').innerHTML = 'disconnected'; + connButton.innerText = 'CONNECT'; + stopAllStreams(); + closePC(); +}); + +async function doOffer() { + const pc = new RTCPeerConnection({ + 'iceServers': [{ + urls: 'stun:stun.l.google.com:19302' + }], + }); + sipPeerConnection = pc; + + pc.onnegotiationneeded = event => console.log('pc.onnegotiationneeded', event); + pc.onicecandidate = event => trickle({ candidate: event.candidate }); + pc.oniceconnectionstatechange = () => { + if (pc.iceConnectionState === 'failed' || pc.iceConnectionState === 'closed') { + closePC(pc); + } + }; + pc.ontrack = event => { + console.log('pc.ontrack', event); + + event.track.onunmute = evt => { + console.log('track.onunmute', evt); + /* TODO set srcObject in this callback */ + }; + event.track.onmute = evt => { + console.log('track.onmute', evt); + }; + event.track.onended = evt => { + console.log('track.onended', evt); + }; + + const remoteStream = event.streams[0]; + setRemoteAudioElement(remoteStream); + }; + + const localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }); + + console.log('getUserMedia OK'); + + setLocalAudioElement(localStream); + + localStream.getTracks().forEach(track => { + console.log('adding track', track); + pc.addTrack(track, localStream); + }); + + + const offer = await sipPeerConnection.createOffer(); + console.log('create offer OK'); + await sipPeerConnection.setLocalDescription(offer); + console.log('set local sdp OK'); + return offer; +} + +async function doAnswer(offer) { + const pc = new RTCPeerConnection({ + 'iceServers': [{ + urls: 'stun:stun.l.google.com:19302' + }], + }); + sipPeerConnection = pc; + + pc.onnegotiationneeded = event => console.log('pc.onnegotiationneeded', event); + pc.onicecandidate = event => trickle({ candidate: event.candidate }); + pc.oniceconnectionstatechange = () => { + if (pc.iceConnectionState === 'failed' || pc.iceConnectionState === 'closed') { + closePC(pc); + } + }; + pc.ontrack = event => { + console.log('pc.ontrack', event); + + event.track.onunmute = evt => { + console.log('track.onunmute', evt); + /* TODO set srcObject in this callback */ + }; + event.track.onmute = evt => { + console.log('track.onmute', evt); + }; + event.track.onended = evt => { + console.log('track.onended', evt); + }; + + const remoteStream = event.streams[0]; + setRemoteAudioElement(remoteStream); + }; + + const localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }); + + console.log('getUserMedia OK'); + + setLocalAudioElement(localStream); + + localStream.getTracks().forEach(track => { + console.log('adding track', track); + pc.addTrack(track, localStream); + }); + + await sipPeerConnection.setRemoteDescription(offer); + console.log('set remote sdp OK'); + const answer = await sipPeerConnection.createAnswer(); + console.log('create answer OK'); + await pc.setLocalDescription(answer); + console.log('set local sdp OK'); + return answer; +} + +function setLocalAudioElement(stream) { + if (stream) { + const audioStreamElem = document.getElementById('localAudio'); + audioStreamElem.autoplay = false; + audioStreamElem.srcObject = stream; + } +} + +function setRemoteAudioElement(stream) { + if (stream) { + const audioStreamElem = document.getElementById('remoteAudio'); + audioStreamElem.autoplay = true; + audioStreamElem.srcObject = stream; + } +} + +function stopAllStreams() { + incoming = null; + if (localAudio.srcObject) { + localAudio.srcObject.getTracks().forEach(track => track.stop()); + localAudio.srcObject = null; + } + if (remoteAudio.srcObject) { + remoteAudio.srcObject.getTracks().forEach(track => track.stop()); + remoteAudio.srcObject = null; + } +} + +function closePC(pc = sipPeerConnection) { + if (!pc) return; + pc.getSenders().forEach(sender => { + if (sender.track) + sender.track.stop(); + }); + pc.getReceivers().forEach(receiver => { + if (receiver.track) + receiver.track.stop(); + }); + pc.onnegotiationneeded = null; + pc.onicecandidate = null; + pc.oniceconnectionstatechange = null; + pc.ontrack = null; + pc.close(); +} \ No newline at end of file diff --git a/examples/sip/package-lock.json b/examples/sip/package-lock.json new file mode 100644 index 0000000..f4cd691 --- /dev/null +++ b/examples/sip/package-lock.json @@ -0,0 +1,1092 @@ +{ + "name": "janode-sip", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "janode-sip", + "license": "ISC", + "dependencies": { + "express": "^4.13.4", + "socket.io": "^4.2.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", + "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", + "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.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/socket.io": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/examples/sip/package.json b/examples/sip/package.json new file mode 100644 index 0000000..efb223f --- /dev/null +++ b/examples/sip/package.json @@ -0,0 +1,30 @@ +{ + "name": "janode-sip", + "description": "Janode SIP app", + "type": "module", + "keywords": [ + "janus", + "webrtc", + "meetecho" + ], + "author": { + "name": "Alessandro Toppi", + "email": "atoppi@meetecho.com" + }, + "repository": { + "type": "git", + "url": "https://github.com/meetecho/janode.git" + }, + "license": "ISC", + "private": true, + "main": "src/index.js", + "dependencies": { + "express": "^4.13.4", + "socket.io": "^4.2.0" + }, + "scripts": { + "build": "npm install --omit=dev", + "build-config": "node -e \"var fs = require('fs');fs.createReadStream('src/config.template.js').pipe(fs.createWriteStream('src/config.js'));\"", + "start": "node src/index.js" + } +} \ No newline at end of file diff --git a/examples/sip/src/config.template.js b/examples/sip/src/config.template.js new file mode 100644 index 0000000..a82aafe --- /dev/null +++ b/examples/sip/src/config.template.js @@ -0,0 +1,16 @@ +export default { + janode: { + address: [{ + url: 'ws://127.0.0.1:8188/', + apisecret: 'secret' + }], + // seconds between retries after a connection setup error + retry_time_secs: 10 + }, + web: { + port: 4443, + bind: '0.0.0.0', + key: '/path/to/key.pem', + cert: '/path/to/cert.pem' + } +}; \ No newline at end of file diff --git a/examples/sip/src/index.js b/examples/sip/src/index.js new file mode 100644 index 0000000..392ead8 --- /dev/null +++ b/examples/sip/src/index.js @@ -0,0 +1,330 @@ +'use strict'; + +import { readFileSync } from 'fs'; +import Janode from '../../../src/janode.js'; +import config from './config.js'; +const { janode: janodeConfig, web: serverConfig } = config; + +import { fileURLToPath } from 'url'; +import { dirname, basename } from 'path'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const { Logger } = Janode; +const LOG_NS = `[${basename(__filename)}]`; +import SipPlugin from '../../../src/plugins/sip-plugin.js'; + +import express from 'express'; +const app = express(); +const options = { + key: serverConfig.key ? readFileSync(serverConfig.key) : null, + cert: serverConfig.cert ? readFileSync(serverConfig.cert) : null, +}; +import { createServer as createHttpsServer } from 'https'; +import { createServer as createHttpServer } from 'http'; +const httpServer = (options.key && options.cert) ? createHttpsServer(options, app) : createHttpServer(app); +import { Server } from 'socket.io'; +const io = new Server(httpServer); + +const scheduleBackEndConnection = (function () { + let task = null; + + return (function (del = 10) { + if (task) return; + Logger.info(`${LOG_NS} scheduled connection in ${del} seconds`); + task = setTimeout(() => { + initBackEnd() + .then(() => task = null) + .catch(() => { + task = null; + scheduleBackEndConnection(); + }); + }, del * 1000); + }); +})(); + + +let janodeSession; + +(function main() { + + initFrontEnd().catch(({ message }) => Logger.error(`${LOG_NS} failure initializing front-end: ${message}`)); + + scheduleBackEndConnection(1); + +})(); + +async function initBackEnd() { + Logger.info(`${LOG_NS} connecting Janode...`); + let connection; + + try { + connection = await Janode.connect(janodeConfig); + Logger.info(`${LOG_NS} connection with Janus created`); + + connection.once(Janode.EVENT.CONNECTION_CLOSED, () => { + Logger.info(`${LOG_NS} connection with Janus closed`); + }); + + connection.once(Janode.EVENT.CONNECTION_ERROR, ({ message }) => { + Logger.info(`${LOG_NS} connection with Janus error (${message})`); + + replyError(io, 'backend-failure'); + + scheduleBackEndConnection(); + }); + + const session = await connection.create(); + Logger.info(`${LOG_NS} session with Janus established`); + janodeSession = session; + + session.once(Janode.EVENT.SESSION_DESTROYED, () => { + Logger.info(`${LOG_NS} session destroyed`); + }); + } + catch (error) { + Logger.error(`${LOG_NS} Janode setup error (${error.message})`); + if (connection) connection.close().catch(() => { }); + + replyError(io, 'backend-failure'); + + throw error; + } +} + +function initFrontEnd() { + if (httpServer.listening) return Promise.reject(new Error('Server already listening')); + + Logger.info(`${LOG_NS} initializing socketio front end...`); + + io.on('connection', function (socket) { + const remote = `[${socket.request.connection.remoteAddress}:${socket.request.connection.remotePort}]`; + Logger.info(`${LOG_NS} ${remote} connection with client established`); + + let sipHandle; + + // start request from client + socket.on('register', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} register received`); + const { _id, data: regdata = {} } = evtdata; + + if (!checkSessions(janodeSession, true, socket, evtdata)) return; + + try { + sipHandle = await janodeSession.attach(SipPlugin); + Logger.info(`${LOG_NS} ${remote} sip handle ${sipHandle.id} attached`); + + // custom sipHandle events + sipHandle.on(SipPlugin.EVENT.SIP_REGISTERING, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle registering`); + replyEvent(socket, 'registering', evtdata); + }); + sipHandle.on(SipPlugin.EVENT.SIP_CALLING, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle calling`); + replyEvent(socket, 'calling', evtdata); + }); + sipHandle.on(SipPlugin.EVENT.SIP_RINGING, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle ringing`); + replyEvent(socket, 'ringing', evtdata); + }); + sipHandle.on(SipPlugin.EVENT.SIP_PROCEEDING, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle proceeding`); + replyEvent(socket, 'proceeding', evtdata); + }); + sipHandle.on(SipPlugin.EVENT.SIP_INCOMING, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle incoming call`); + replyEvent(socket, 'incoming', evtdata); + }); + sipHandle.on(SipPlugin.EVENT.SIP_HANGUP, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle hangup`); + replyEvent(socket, 'hangup', evtdata); + }); + sipHandle.on(SipPlugin.EVENT.SIP_MISSED, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle missed`); + replyEvent(socket, 'missed', evtdata); + }); + sipHandle.on(SipPlugin.EVENT.SIP_INFO, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle info`); + replyEvent(socket, 'info', evtdata); + }); + sipHandle.on(SipPlugin.EVENT.SIP_DTMF, evtdata => { + Logger.info(`${LOG_NS} ${sipHandle.name} sip handle dtmf`); + replyEvent(socket, 'dtmf', evtdata); + }); + + // generic sipHandle events + sipHandle.on(Janode.EVENT.HANDLE_WEBRTCUP, () => Logger.info(`${LOG_NS} ${sipHandle.name} webrtcup event`)); + sipHandle.on(Janode.EVENT.HANDLE_MEDIA, evtdata => Logger.info(`${LOG_NS} ${sipHandle.name} media event ${JSON.stringify(evtdata)}`)); + sipHandle.on(Janode.EVENT.HANDLE_SLOWLINK, evtdata => Logger.info(`${LOG_NS} ${sipHandle.name} slowlink event ${JSON.stringify(evtdata)}`)); + sipHandle.on(Janode.EVENT.HANDLE_HANGUP, evtdata => Logger.info(`${LOG_NS} ${sipHandle.name} hangup event ${JSON.stringify(evtdata)}`)); + sipHandle.on(Janode.EVENT.HANDLE_DETACHED, () => Logger.info(`${LOG_NS} ${sipHandle.name} detached event`)); + sipHandle.on(Janode.EVENT.HANDLE_TRICKLE, evtdata => Logger.info(`${LOG_NS} ${sipHandle.name} trickle event ${JSON.stringify(evtdata)}`)); + + const response = await sipHandle.register(regdata); + replyEvent(socket, 'registered', response, _id); + + Logger.info(`${LOG_NS} ${remote} registered sent`); + } catch ({ message }) { + Logger.error(`${LOG_NS} ${remote} error registering (${message})`); + replyError(socket, message, regdata, _id); + } + + }); + + // start call + socket.on('call', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} call received`); + const { _id, data: calldata = {} } = evtdata; + + if (!checkSessions(janodeSession, sipHandle, socket, evtdata)) return; + + try { + const { uri, jsep: offer } = calldata; + const response = await sipHandle.call({ + uri, + jsep: offer, + }); + replyEvent(socket, 'accepted', response, _id); + Logger.info(`${LOG_NS} ${remote} accepted sent`); + } catch ({ message }) { + Logger.error(`${LOG_NS} ${remote} error calling (${message})`); + replyError(socket, message, calldata, _id); + } + }); + + // answer call + socket.on('accept', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} accept received`); + const { _id, data: acceptdata = {} } = evtdata; + + if (!checkSessions(janodeSession, sipHandle, socket, evtdata)) return; + + try { + const { jsep: answer } = acceptdata; + const response = await sipHandle.accept({ + jsep: answer, + }); + replyEvent(socket, 'accepted', response, _id); + Logger.info(`${LOG_NS} ${remote} accepted sent`); + } catch ({ message }) { + Logger.error(`${LOG_NS} ${remote} error accepting (${message})`); + replyError(socket, message, acceptdata, _id); + } + }); + + socket.on('hangup', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} hangup received`); + const { _id, data: hangupdata = {} } = evtdata; + + if (!checkSessions(janodeSession, sipHandle, socket, evtdata)) return; + + try { + await sipHandle.sip_hangup(); + replyEvent(socket, 'hangup', {}, _id); + Logger.info(`${LOG_NS} ${remote} hangup sent`); + } catch ({ message }) { + Logger.error(`${LOG_NS} ${remote} error hanging up (${message})`); + replyError(socket, message, hangupdata, _id); + } + }); + + socket.on('decline', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} decline received`); + const { _id, data: declinedata = {} } = evtdata; + + if (!checkSessions(janodeSession, sipHandle, socket, evtdata)) return; + + try { + await sipHandle.decline(); + replyEvent(socket, 'declined', {}, _id); + Logger.info(`${LOG_NS} ${remote} declined sent`); + } catch ({ message }) { + Logger.error(`${LOG_NS} ${remote} error declining (${message})`); + replyError(socket, message, declinedata, _id); + } + }); + + // trickle candidate from the client + socket.on('trickle', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} trickle received`); + const { _id, data: trickledata = {} } = evtdata; + + if (!checkSessions(janodeSession, sipHandle, socket, evtdata)) return; + + sipHandle.trickle(trickledata.candidate).catch(({ message }) => replyError(socket, message, trickledata, _id)); + }); + + // trickle complete signal from the client + socket.on('trickle-complete', async (evtdata = {}) => { + Logger.info(`${LOG_NS} ${remote} trickle-complete received`); + const { _id, data: trickledata = {} } = evtdata; + + if (!checkSessions(janodeSession, sipHandle, socket, evtdata)) return; + + sipHandle.trickleComplete().catch(({ message }) => replyError(socket, message, trickledata, _id)); + }); + + // socket disconnection event + socket.on('disconnect', () => { + Logger.info(`${LOG_NS} ${remote} disconnected socket`); + //request sipHandle detach + if (sipHandle) sipHandle.detach().catch(() => { }); + }); + }); + + // disable etag and view caching for all app + app.set('etag', false).set('view cache', false); + + // static content + app.use('/janode', express.static(__dirname + '/../html/', { + etag: false, + lastModified: false, + maxAge: 0, + })); + + // http server binding + return new Promise((resolve, reject) => { + // web server binding + httpServer.listen( + serverConfig.port, + serverConfig.bind, + () => { + Logger.info(`${LOG_NS} server listening on ${(options.key && options.cert) ? 'https' : 'http'}://${serverConfig.bind}:${serverConfig.port}/janode`); + resolve(); + } + ); + + httpServer.on('error', e => reject(e)); + }); +} + +function checkSessions(session, handle, socket, { data, _id }) { + if (!session) { + replyError(socket, 'session-not-available', data, _id); + return false; + } + if (!handle) { + replyError(socket, 'handle-not-available', data, _id); + return false; + } + return true; +} + +function replyEvent(socket, evtname, data, _id) { + const evtdata = { + data, + }; + if (_id) evtdata._id = _id; + + socket.emit(evtname, evtdata); +} + +function replyError(socket, message, request, _id) { + const evtdata = { + error: message, + }; + if (request) evtdata.request = request; + if (_id) evtdata._id = _id; + + socket.emit('sip-error', evtdata); +} \ No newline at end of file diff --git a/package.json b/package.json index 1af2d44..22123f2 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ ".": "./src/janode.js", "./plugins/audiobridge": "./src/plugins/audiobridge-plugin.js", "./plugins/echotest": "./src/plugins/echotest-plugin.js", + "./plugins/sip": "./src/plugins/sip-plugin.js", "./plugins/streaming": "./src/plugins/streaming-plugin.js", "./plugins/videoroom": "./src/plugins/videoroom-plugin.js" }, diff --git a/src/handle.js b/src/handle.js index 715c4b4..0e293bb 100644 --- a/src/handle.js +++ b/src/handle.js @@ -251,10 +251,6 @@ class Handle extends EventEmitter { const error = new Error('unmanaged event'); this.closeTransactionWithError(transaction, error); } - else { - /* If handleMessage has a truthy return close tx with success */ - this.closeTransactionWithSuccess(transaction, janus_message); - } break; } @@ -389,6 +385,10 @@ class Handle extends EventEmitter { request.handle_id = request.handle_id || this.id; } + decorateRequest(request) { + this._decorateRequest(request); + } + /** * Helper method used by plugins to create a new plugin event and assign it to a janus message. * @@ -477,9 +477,10 @@ class Handle extends EventEmitter { * Send a request from this handle. * * @param {Object} request - * @returns {Promise} A Promise resolving with the response to the request + * @param {number} [timeout_ms=0] + * @returns {Promise} A promise resolving with the response to the request */ - async sendRequest(request) { + async sendRequest(request, timeout_ms = 0) { /* Input check */ if (typeof request !== 'object' || !request) { const error = new Error('request must be an object'); @@ -500,7 +501,7 @@ class Handle extends EventEmitter { return new Promise((resolve, reject) => { /* Create a new transaction if the transaction does not exist */ /* Use promise resolve and reject fn as callbacks for the transaction */ - this._tm.createTransaction(request.transaction, this, request.janus, resolve, reject); + this._tm.createTransaction(request.transaction, this, request.janus, resolve, reject, timeout_ms); /* Send this message through the parent janode session */ this.session.sendRequest(request).catch(error => { diff --git a/src/plugins/sip-plugin.js b/src/plugins/sip-plugin.js new file mode 100644 index 0000000..2641a21 --- /dev/null +++ b/src/plugins/sip-plugin.js @@ -0,0 +1,612 @@ +'use strict'; + +/** + * This module contains the implementation of the SIP plugin (ref. {@link https://janus.conf.meetecho.com/docs/sip.html}). + * @module sip-plugin + */ + +import Handle from '../handle.js'; +import { JANODE } from '../protocol.js'; + +/* The plugin ID exported in the plugin descriptor */ +const PLUGIN_ID = 'janus.plugin.sip'; + +/* These are the requests defined for the Janus SIP plugin API */ +const REQUEST_REGISTER = 'register'; +const REQUEST_CALL = 'call'; +const REQUEST_ACCEPT = 'accept'; +const REQUEST_HANGUP = 'hangup'; +const REQUEST_DECLINE = 'decline'; + +/* These are the events/responses that the Janode plugin will manage */ +/* Some of them will be exported in the plugin descriptor */ +const PLUGIN_EVENT = { + REGISTERED: 'sip_registered', + REGISTERING: 'sip_registering', + CALLING: 'sip_calling', + RINGING: 'sip_ringing', + PROCEEDING: 'sip_proceeding', + INCOMING: 'sip_incoming', + HANGUP: 'sip_hangup', + HANGINGUP: 'sip_hangingup', + DECLINING: 'declining', + ACCEPTED: 'sip_accepted', + MISSED: 'sip_missed', + INFO: 'sip_info', + DTMF: 'sip_dtmf', + ERROR: 'sip_error', + ERROR_EVENT: 'sip_error_event', +}; + +/** + * The class implementing the SIP plugin (ref. {@link https://janus.conf.meetecho.com/docs/sip.html}).
+ * + * It extends the base Janode Handle class and overrides the base "handleMessage" method.
+ * + * Moreover it defines some methods to support SIP operations.
+ * + * @hideconstructor + * @extends module:handle~Handle + */ +class SipHandle extends Handle { + /** + * Create a Janode SIP handle. + * + * @param {module:session~Session} session - A reference to the parent session + * @param {number} id - The handle identifier + */ + constructor(session, id) { + super(session, id); + this._pendingRegister = null; + this._pendingCalls = {}; + + this.on(JANODE.EVENT.HANDLE_HANGUP, _ => { + this._pendingRegister = null; + this._pendingCalls = {}; + }); + this.on(JANODE.EVENT.HANDLE_DETACHED, _ => { + this._pendingRegister = null; + this._pendingCalls = {}; + }); + } + + /** + * The custom "handleMessage" needed for handling SIP plugin messages. + * + * @private + * @param {Object} janus_message + * @returns {Object} A falsy value for unhandled events, a truthy value for handled events + */ + handleMessage(janus_message) { + const { plugindata, transaction } = janus_message; + if (plugindata && plugindata.data && plugindata.data.sip) { + /** + * @type {SipData} + */ + const message_data = plugindata.data; + const { sip, result, call_id, error, error_code } = message_data; + + /* The event can not be recognized, return a falsy value */ + if (!error && sip !== 'event' && !result.event) + return null; + + /* Prepare an object for the output Janode event */ + const janode_event = this._newPluginEvent(janus_message); + + /* Add call id information if available */ + if (call_id) { + janode_event.data.call_id = call_id; + this._pendingCalls[call_id] = this._pendingCalls[call_id] || {}; + } + + /* Plugin messaging error (not related to SIP requests) */ + if (error) { + janode_event.event = PLUGIN_EVENT.ERROR; + janode_event.data = new Error(`${error_code} ${error}`); + /* In case of error, close a transaction */ + this.closeTransactionWithError(transaction, janode_event.data); + return janode_event; + } + + /* Emit the event to the application */ + let emit = false; + + /* Close the related janus transaction */ + const CLOSE_TX_NO = 0; + const CLOSE_TX_SUCCESS = 1; + const CLOSE_TX_ERROR = -1; + let closeTx = CLOSE_TX_NO; + let txId = transaction; + + switch (result.event) { + + /* Registering event */ + case 'registering': + janode_event.event = PLUGIN_EVENT.REGISTERING; + closeTx = CLOSE_TX_NO; + emit = true; + break; + + case 'registration_failed': + janode_event.event = PLUGIN_EVENT.ERROR_EVENT; + janode_event.data = new Error(`${result.code} ${result.reason}`); + closeTx = CLOSE_TX_ERROR; + txId = transaction || this._pendingRegister; + emit = false; + break; + + case 'registered': + janode_event.event = PLUGIN_EVENT.REGISTERED; + janode_event.data.username = result.username; + janode_event.data.register_sent = result.register_sent; + closeTx = CLOSE_TX_SUCCESS; + txId = transaction || this._pendingRegister; + emit = false; + break; + + case 'calling': + janode_event.event = PLUGIN_EVENT.CALLING; + closeTx = CLOSE_TX_NO; + emit = true; + break; + + case 'ringing': + janode_event.event = PLUGIN_EVENT.RINGING; + closeTx = CLOSE_TX_NO; + emit = true; + break; + + case 'proceeding': + janode_event.event = PLUGIN_EVENT.PROCEEDING; + closeTx = CLOSE_TX_NO; + emit = true; + break; + + /* Inbound call */ + case 'incomingcall': { + janode_event.event = PLUGIN_EVENT.INCOMING; + /* Store the incoming call URI */ + const call = this._pendingCalls[call_id]; + if (call) { + call.incoming = result.username; + } + janode_event.data.username = result.username; + janode_event.data.callee = result.callee; + janode_event.data.display_name = result.displayname || undefined; + closeTx = CLOSE_TX_NO; + emit = true; + break; + } + + case 'hangup': { + /* Is there is a pending call without a reply? */ + const call = this._pendingCalls[call_id]; + if (call && !call.accepted && !call.declined && !call.incoming) { + janode_event.event = PLUGIN_EVENT.ERROR_EVENT; + janode_event.data = new Error(`${result.code} ${result.reason}`); + closeTx = CLOSE_TX_ERROR; + } + /* Async hangup */ + else { + janode_event.event = PLUGIN_EVENT.HANGUP; + closeTx = CLOSE_TX_NO; + emit = true; + } + delete this._pendingCalls[call_id]; + break; + } + + case 'hangingup': + janode_event.event = PLUGIN_EVENT.HANGINGUP; + closeTx = CLOSE_TX_SUCCESS; + emit = false; + break; + + case 'declining': { + janode_event.event = PLUGIN_EVENT.DECLINING; + const call = this._pendingCalls[call_id]; + if (call) { + call.declined = true; + } + closeTx = CLOSE_TX_SUCCESS; + emit = false; + break; + } + + /* A call has been accepted */ + case 'accepted': { + janode_event.event = PLUGIN_EVENT.ACCEPTED; + janode_event.data.username = result.username || this._pendingCalls[call_id].incoming; + const call = this._pendingCalls[call_id]; + if (call) { + call.accepted = true; + } + closeTx = CLOSE_TX_SUCCESS; + emit = false; + break; + } + + /* Call has been missed */ + case 'missed_call': { + delete this._pendingCalls[call_id]; + janode_event.event = PLUGIN_EVENT.MISSED; + janode_event.data.callee = result.callee; + janode_event.data.caller = result.caller; + closeTx = CLOSE_TX_NO; + emit = true; + break; + } + + /* SIP INFO */ + case 'info': { + janode_event.event = PLUGIN_EVENT.INFO; + janode_event.data.sender = result.sender; + if (result.displayname) { + janode_event.data.displayname = result.displayname; + } + janode_event.data.type = result.type; + janode_event.data.content = result.content; + if (result.headers) { + janode_event.data.headers = result.headers; + } + emit = true; + break; + } + + /* RFC2833 DTMF */ + case 'dtmf': { + janode_event.event = PLUGIN_EVENT.DTMF; + janode_event.data.sender = result.sender; + janode_event.data.signal = result.signal; + janode_event.data.duration = result.duration; + emit = true; + break; + } + } + + /* The event has been handled */ + if (janode_event.event) { + if (closeTx === CLOSE_TX_SUCCESS) + this.closeTransactionWithSuccess(txId, janus_message); + if (closeTx === CLOSE_TX_ERROR) + this.closeTransactionWithError(txId, janode_event.data); + if (emit) + this.emit(janode_event.event, janode_event.data); + return janode_event; + } + } + + /* The event has not been handled, return a falsy value */ + return null; + } + + /** + * Register to the SIP plugin (sending of a SIP REGISTER is optional). + * + * @param {Object} params + * @param {string} [params.type] - optional SIP session type, either "guest" or "helper" + * @param {boolean} [params.send_register] - True to send a SIP register + * @param {boolean} [params.force_udp] - True to force UDP for the SIP messaging + * @param {boolean} [params.force_tcp] - True to force TCP for the SIP messaging + * @param {boolean} [params.sips] - True to configure a SIPS URI too when registering + * @param {boolean} [params.rfc2543_cancel] - True to configure sip client to CANCEL pending INVITEs without having received a provisional response + * @param {string} params.username - The SIP URI to register + * @param {string} [params.secret] - The password to use, if any + * @param {string} [params.ha1_secret] - The prehashed password to use, if any + * @param {string} [params.display_name] - The display name to use when sending SIP REGISTER + * @param {string} [params.proxy] - The server to register at (not needed for guests) + * @param {string} [params.outbound_proxy] - The server to register at (not needed for guests) + * @param {number} [params.register_ttl] - The number of seconds after which the registration should expire + * + * @returns {Promise} + */ + async register({ type, send_register, force_udp, force_tcp, sips, rfc2543_cancel, username, secret, ha1_secret, display_name, proxy, outbound_proxy, register_ttl }) { + const body = { + request: REQUEST_REGISTER, + username, + }; + + if (typeof type === 'string') body.type = type; + if (typeof send_register === 'boolean') body.send_register = send_register; + if (typeof force_udp === 'boolean') body.force_udp = force_udp; + if (typeof force_tcp === 'boolean') body.force_tcp = force_tcp; + if (typeof sips === 'boolean') body.sips = sips; + if (typeof rfc2543_cancel === 'boolean') body.rfc2543_cancel = rfc2543_cancel; + if (typeof secret === 'string') body.secret = secret; + if (typeof ha1_secret === 'string') body.ha1_secret = ha1_secret; + if (typeof display_name === 'string') body.display_name = display_name; + if (typeof proxy === 'string') body.proxy = proxy; + if (typeof outbound_proxy === 'string') body.outbound_proxy = outbound_proxy; + if (typeof register_ttl === 'number') body.register_ttl = register_ttl; + + const request = { + janus: 'message', + body, + }; + this.decorateRequest(request); + this._pendingRegister = request.transaction; + + const response = await this.sendRequest(request, 10000); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.REGISTERED) { + evtdata.username = username; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Start a SIP call. + * + * @param {Object} params + * @param {string} params.uri - The SIP URI to call + * @param {string} [params.call_id] - The user-defined value of Call-ID SIP header used in all SIP requests throughout the call + * @param {string} [params.authuser] - The username to use to authenticate as to call, only needed in case authentication is needed and no REGISTER was sent + * @param {string} [params.secret] - The password to use for authentication, if any + * @param {string} [params.ha1_secret] - The prehashed password to use for authentication, if any + * @param {RTCSessionDescription} params.jsep - JSEP offer + * @returns {Promise} + */ + async call({ uri, call_id, authuser, secret, ha1_secret, jsep }) { + if (typeof jsep === 'object' && jsep && jsep.type !== 'offer') { + const error = new Error('jsep must be an offer'); + return Promise.reject(error); + } + + const body = { + request: REQUEST_CALL, + uri, + }; + + if (typeof call_id === 'string') body.call_id = call_id; + if (typeof authuser === 'string') body.authuser = authuser; + if (typeof secret === 'string') body.secret = secret; + if (typeof ha1_secret === 'string') body.ha1_secret = ha1_secret; + + const request = { + janus: 'message', + body, + jsep, + }; + this.decorateRequest(request); + + const response = await this.sendRequest(request, 120000); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.ACCEPTED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Accept an incoming SIP call. + * + * @param {Object} params + * @param {RTCSessionDescription} params.jsep - JSEP answer + * @returns {Promise} + */ + async accept({ jsep }) { + if (typeof jsep === 'object' && jsep && jsep.type !== 'answer') { + const error = new Error('jsep must be an answer'); + return Promise.reject(error); + } + const body = { + request: REQUEST_ACCEPT, + }; + + const request = { + janus: 'message', + body, + jsep, + }; + this.decorateRequest(request); + + const response = await this.sendRequest(request, 10000); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.ACCEPTED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Hangup a SIP call. + * + * @returns {Promise} + */ + async sip_hangup() { + const body = { + request: REQUEST_HANGUP, + }; + + const request = { + janus: 'message', + body, + }; + this.decorateRequest(request); + + const response = await this.sendRequest(request, 10000); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.HANGINGUP) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Decline an incoming SIP call. + * + * @returns {Promise} + */ + async decline() { + const body = { + request: REQUEST_DECLINE, + }; + + const request = { + janus: 'message', + body, + }; + this.decorateRequest(request); + + const response = await this.sendRequest(request, 10000); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.DECLINING) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } +} + +/** + * The payload of the plugin message (cfr. Janus docs). + * {@link https://janus.conf.meetecho.com/docs/sip.html} + * + * @private + * @typedef {Object} SipData + */ + +/** + * The success event for a register request + * + * @typedef {Object} SIP_EVENT_REGISTERED + * @property {string} username - The URI that has been registered + * @property {boolean} register_sent - True is a REGISTER has been sent + */ + +/** + * The success event for an accept request + * + * @typedef {Object} SIP_EVENT_ACCEPTED + * @property {string} call_id + * @property {string} username + * @property {RTCSessionDescription} [jsep] + */ + +/** + * The success event for an hangup request + * + * @typedef {Object} SIP_EVENT_HANGINGUP + * @property {string} call_id + */ + +/** + * The success event for a decline request + * + * @typedef {Object} SIP_EVENT_DECLINING + * @property {string} call_id + */ + +/** + * The exported plugin descriptor. + * + * @type {Object} + * @property {string} id - The plugin identifier used when attaching to Janus + * @property {module:sip-plugin~SipHandle} Handle - The custom class implementing the plugin + * @property {Object} EVENT - The events emitted by the plugin + * @property {string} EVENT.SIP_REGISTERING {@link module:sip-plugin~SipHandle#event:SIP_REGISTERING SIP_REGISTERING} + * @property {string} EVENT.SIP_CALLING {@link module:sip-plugin~SipHandle#event:SIP_CALLING SIP_CALLING} + * @property {string} EVENT.SIP_RINGING {@link module:sip-plugin~SipHandle#event:SIP_RINGING SIP_RINGING} + * @property {string} EVENT.SIP_PROCEEDING {@link module:sip-plugin~SipHandle#event:SIP_PROCEEDING SIP_PROCEEDING} + * @property {string} EVENT.SIP_INCOMING {@link module:sip-plugin~SipHandle#event:SIP_INCOMING SIP_INCOMING} + * @property {string} EVENT.SIP_HANGUP {@link module:sip-plugin~SipHandle#event:SIP_HANGUP SIP_HANGUP} + * @property {string} EVENT.SIP_MISSED {@link module:sip-plugin~SipHandle#event:SIP_MISSED SIP_MISSED} + * @property {string} EVENT.SIP_INFO {@link module:sip-plugin~SipHandle#event:SIP_INFO SIP_INFO} + * @property {string} EVENT.SIP_DTMF {@link module:sip-plugin~SipHandle#event:SIP_DTMF SIP_DTMF} + */ +export default { + id: PLUGIN_ID, + Handle: SipHandle, + EVENT: { + /** + * The event notifying a register is in progress + * + * @event module:sip-plugin~SipHandle#event:SIP_REGISTERING + * @type {Object} + */ + SIP_REGISTERING: PLUGIN_EVENT.REGISTERING, + + /** + * Event for a SIP call in progress + * + * @event module:sip-plugin~SipHandle#event:SIP_CALLING + * @type {Object} + * @property {string} call_id - SIP Call-ID header for related call + */ + SIP_CALLING: PLUGIN_EVENT.CALLING, + + /** + * Event for a SIP call ringing + * + * @event module:sip-plugin~SipHandle#event:SIP_RINGING + * @type {Object} + * @property {string} call_id - SIP Call-ID header for related call + */ + SIP_RINGING: PLUGIN_EVENT.RINGING, + + /** + * Event for a SIP call proceeding + * + * @event module:sip-plugin~SipHandle#event:SIP_PROCEEDING + * @type {Object} + * @property {string} call_id - SIP Call-ID header for related call + */ + SIP_PROCEEDING: PLUGIN_EVENT.PROCEEDING, + + /** + * Event for an incoming SIP call + * + * @event module:sip-plugin~SipHandle#event:SIP_INCOMING + * @type {Object} + * @property {string} call_id - SIP Call-ID header for related call + * @property {string} callee - SIP URI that was called + * @property {string} display_name - Display name of the caller + * @property {string} username - SIP URI of the caller + * @property {RTCSessionDescription} [jsep] - The JSEP offer + */ + SIP_INCOMING: PLUGIN_EVENT.INCOMING, + + /** + * Event for a SIP call hangup + * + * @event module:sip-plugin~SipHandle#event:SIP_HANGUP + * @type {Object} + * @property {string} call_id - SIP Call-ID header for related call + */ + SIP_HANGUP: PLUGIN_EVENT.HANGUP, + + /** + * Event for a missed SIP call + * + * @event module:sip-plugin~SipHandle#event:SIP_MISSED + * @type {Object} + * @property {string} call_id - SIP Call-ID header for related call + * @property {string} callee - SIP URI that was called + * @property {string} caller - SIP URI of the caller + */ + SIP_MISSED: PLUGIN_EVENT.MISSED, + + /** + * @event module:sip-plugin~SipHandle#event:SIP_INFO + * @type {Object} + * @property {string} sender - SIP URI of the message sender + * @property {string} [call_id] - SIP Call-ID header for related call + * @property {string} [displayname] - Display name of the sender + * @property {string} type - Content type of the message + * @property {string} content - Content of the message + * @property {Object} [headers] - Custom headers extracted from SIP event + */ + SIP_INFO: PLUGIN_EVENT.INFO, + + /** + * @event module:sip-plugin~SipHandle#event:SIP_DTMF + * @type {Object} + * @property {string} sender - SIP URI of the DTMF sender + * @property {string} [call_id] - SIP Call-ID header for related call + * @property {string} signal - The DTMF tone signal + * @property {number} duration - The DTMF tone duration + */ + SIP_DTMF: PLUGIN_EVENT.DTMF, + }, +}; \ No newline at end of file diff --git a/src/tmanager.js b/src/tmanager.js index 04ffb19..f49629c 100644 --- a/src/tmanager.js +++ b/src/tmanager.js @@ -134,9 +134,10 @@ class TransactionManager { * @param {string} request - The janus request for the pending transaction * @param {function} done - The success callback * @param {function} error - The error callback + * @param {number} [timeout_ms=0] - The timeout of the transaction * @returns {PendingTransaction|void} The newly created transaction, or nothing if the id already exists */ - createTransaction(id, owner, request, done, error) { + createTransaction(id, owner, request, done, error, timeout_ms = 0) { if (this.has(id)) return; const tx = { id, @@ -145,6 +146,15 @@ class TransactionManager { done, error, }; + if (timeout_ms > 0) { + const timeout = setTimeout(_ => { + this.delete(id); + error(new Error('Transaction timed out!')); + Logger.error(`${LOG_NS} [${owner.id}] closed with timeout transaction ${id}, request "${request}"`); + }, timeout_ms); + tx.timeout = timeout; + } + this.set(id, tx); Logger.verbose(`${LOG_NS} [${tx.owner.id}] created new transaction ${id}, request "${tx.request}"`); return tx; @@ -163,6 +173,7 @@ class TransactionManager { const tx = this.get(id); if (!tx) return; if (tx.owner !== owner) return; + clearTimeout(tx.timeout); this.delete(id); tx.error(error); Logger.verbose(`${LOG_NS} [${tx.owner.id}] closed with error transaction ${id}, request "${tx.request}"`); @@ -197,6 +208,7 @@ class TransactionManager { const tx = this.get(id); if (!tx) return; if (tx.owner !== owner) return; + clearTimeout(tx.timeout); this.delete(id); tx.done(data); Logger.verbose(`${LOG_NS} [${tx.owner.id}] closed with success transaction ${id}, request "${tx.request}"`); From f6142788b7a8b88e0a8908a1521e815756d2c53c Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Tue, 3 Jun 2025 17:54:18 +0200 Subject: [PATCH 110/114] package.json: export Handle class under janode/handle --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 22123f2..202daaa 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "main": "./src/janode.js", "exports": { ".": "./src/janode.js", + "./handle": "./src/handle.js", "./plugins/audiobridge": "./src/plugins/audiobridge-plugin.js", "./plugins/echotest": "./src/plugins/echotest-plugin.js", "./plugins/sip": "./src/plugins/sip-plugin.js", From fd50db88d12afdacfac848fdb674510a655e7e59 Mon Sep 17 00:00:00 2001 From: Alessandro Toppi Date: Wed, 4 Jun 2025 23:35:16 +0200 Subject: [PATCH 111/114] misc: add pre-release helper script (useful for preparing a new release) --- .gitignore | 1 - pre-release.sh | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100755 pre-release.sh diff --git a/.gitignore b/.gitignore index 1130b23..67974c9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ bundle.js *.log *.pem *.crt -*.sh !.eslintrc.json !package.json diff --git a/pre-release.sh b/pre-release.sh new file mode 100755 index 0000000..d08bac2 --- /dev/null +++ b/pre-release.sh @@ -0,0 +1,11 @@ +#!/bin/bash -eu + +REL=$1 + +if [ -z "$REL" ]; then + echo "A release name must be specified" + exit 1 +fi + +npm version "$REL" -m "version: bump to $REL" +npm publish --dry-run From 1273c10aa352bd5dab9a0b14573eafd930f1e511 Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Tue, 24 Jun 2025 14:52:55 +0200 Subject: [PATCH 112/114] Add support for Record&Play plugin (#60) Co-authored-by: Alessandro Toppi --- README.md | 3 +- package.json | 1 + src/plugins/recordplay-plugin.js | 526 +++++++++++++++++++++++++++++++ 3 files changed, 529 insertions(+), 1 deletion(-) create mode 100644 src/plugins/recordplay-plugin.js diff --git a/README.md b/README.md index 95d1c30..6966403 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ The supported Janus plugins are: - Streaming - VideoRoom - SIP +- Record&Play The library is available on [npm](https://www.npmjs.com/package/janode) and the source code is on [github](https://github.com/meetecho/janode). @@ -159,4 +160,4 @@ Then use the npm script: npm run build-docs ``` -Documentation in HTML format will be built under the `docs` folder. \ No newline at end of file +Documentation in HTML format will be built under the `docs` folder. diff --git a/package.json b/package.json index 202daaa..724bac2 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "./handle": "./src/handle.js", "./plugins/audiobridge": "./src/plugins/audiobridge-plugin.js", "./plugins/echotest": "./src/plugins/echotest-plugin.js", + "./plugins/recordplay": "./src/plugins/recordplay-plugin.js", "./plugins/sip": "./src/plugins/sip-plugin.js", "./plugins/streaming": "./src/plugins/streaming-plugin.js", "./plugins/videoroom": "./src/plugins/videoroom-plugin.js" diff --git a/src/plugins/recordplay-plugin.js b/src/plugins/recordplay-plugin.js new file mode 100644 index 0000000..7c97777 --- /dev/null +++ b/src/plugins/recordplay-plugin.js @@ -0,0 +1,526 @@ +'use strict'; + +/** + * This module contains the implementation of the Record&Play plugin (ref. {@link https://janus.conf.meetecho.com/docs/recordplay.html}). + * @module recordplay-plugin + */ + +import Handle from '../handle.js'; + +/* The plugin ID exported in the plugin descriptor */ +const PLUGIN_ID = 'janus.plugin.recordplay'; + +/* These are the requests defined for the Janus RecordPlay API */ +const REQUEST_LIST = 'list'; +const REQUEST_UPDATE = 'update'; +const REQUEST_RECORD = 'record'; +const REQUEST_PLAY = 'play'; +const REQUEST_START = 'start'; +const REQUEST_CONFIGURE = 'configure'; +const REQUEST_PAUSE = 'pause'; +const REQUEST_RESUME = 'resume'; +const REQUEST_STOP = 'stop'; + +/* These are the events/responses that the Janode plugin will manage */ +/* Some of them will be exported in the plugin descriptor */ +const PLUGIN_EVENT = { + RECORDINGS_LIST: 'recordplay_list', + RECORDING: 'recordplay_recording', + CONFIGURED: 'recordplay_configured', + PAUSED: 'recordplay_paused', + RESUMED: 'recordplay_resumed', + PREPARING: 'recordplay_preparing', + PLAYING: 'recordplay_playing', + STOPPED: 'recordplay_stopped', + SLOW_LINK: 'recordplay_slowlink', + DONE: 'recordplay_done', + SUCCESS: 'recordplay_success', + ERROR: 'recordplay_error', +}; + +/** + * The class implementing the Record&Play plugin (ref. {@link https://janus.conf.meetecho.com/docs/recordplay.html}).
+ * + * It extends the base Janode Handle class and overrides the base "handleMessage" method.
+ * + * Moreover it defines many methods to support RecordPlay operations. + * + * @hideconstructor + * @extends module:handle~Handle + */ +class RecordPlayHandle extends Handle { + /** + * Create a Janode RecordPlay handle. + * + * @param {module:session~Session} session - A reference to the parent session + * @param {number} id - The handle identifier + */ + constructor(session, id) { + super(session, id); + } + + /** + * The custom "handleMessage" needed for handling RecordPlay messages. + * + * @private + * @param {Object} janus_message + * @returns {Object} A falsy value for unhandled events, a truthy value for handled events + */ + handleMessage(janus_message) { + const { plugindata, transaction } = janus_message; + if (plugindata && plugindata.data && plugindata.data.recordplay) { + /** + * @type {RecordPlayData} + */ + const message_data = plugindata.data; + const { recordplay, error, error_code } = message_data; + + /* Prepare an object for the output Janode event */ + const janode_event = this._newPluginEvent(janus_message); + + /* The plugin will emit an event only if the handle does not own the transaction */ + /* That means that a transaction has already been closed or this is an async event */ + const emit = (this.ownsTransaction(transaction) === false); + + switch (recordplay) { + + /* Got a list of recordings */ + case 'list': + /* Recordings list API */ + janode_event.event = PLUGIN_EVENT.RECORDINGS_LIST; + if (typeof message_data.list !== 'undefined') + janode_event.data.list = message_data.list; + break; + + /* Update success */ + case 'ok': + /* "ok" is treated as "success" */ + janode_event.event = PLUGIN_EVENT.SUCCESS; + break; + + /* Configure success */ + case 'configure': + /* Configure API */ + janode_event.event = PLUGIN_EVENT.CONFIGURED; + if (typeof message_data.result !== 'undefined') + janode_event.data.settings = message_data.result.settings; + break; + + /* Generic event (e.g. errors) */ + case 'event': + /* RecordPlay error */ + if (error) { + janode_event.event = PLUGIN_EVENT.ERROR; + janode_event.data = new Error(`${error_code} ${error}`); + /* In case of error, close a transaction */ + this.closeTransactionWithError(transaction, janode_event.data); + break; + } + /* Update for this handle */ + if (typeof message_data.result !== 'undefined') { + if (typeof message_data.result.status !== 'undefined') { + if (typeof message_data.result.id !== 'undefined') + janode_event.data.id = message_data.result.id; + if (typeof message_data.result.is_private !== 'undefined') + janode_event.data.is_private = message_data.result.is_private; + if (typeof message_data.result.media !== 'undefined') + janode_event.data.media = message_data.result.media; + if (typeof message_data.result.uplink !== 'undefined') + janode_event.data.uplink = message_data.result.uplink; + switch (message_data.result.status) { + case 'recording': + janode_event.event = PLUGIN_EVENT.RECORDING; + break; + case 'paused': + janode_event.event = PLUGIN_EVENT.PAUSED; + break; + case 'resumed': + janode_event.event = PLUGIN_EVENT.RESUMED; + break; + case 'preparing': + janode_event.event = PLUGIN_EVENT.PREPARING; + break; + case 'playing': + janode_event.event = PLUGIN_EVENT.PLAYING; + break; + case 'stopped': + janode_event.event = PLUGIN_EVENT.STOPPED; + break; + case 'slow_link': + janode_event.event = PLUGIN_EVENT.SLOW_LINK; + break; + case 'done': + janode_event.event = PLUGIN_EVENT.DONE; + break; + } + } + break; + } + } + + /* The event has been handled */ + if (janode_event.event) { + /* Try to close the transaction */ + this.closeTransactionWithSuccess(transaction, janus_message); + /* If the transaction was not owned, emit the event */ + if (emit) this.emit(janode_event.event, janode_event.data); + return janode_event; + } + } + + /* The event has not been handled, return a falsy value */ + return null; + } + + /*----------*/ + /* USER API */ + /*----------*/ + + /* These are the APIs that users need to work with the recordplay plugin */ + + /** + * List recordings. + * + * @param {Object} params + * @param {string} [params.admin_key] - The optional admin key needed for invoking the API + * @returns {Promise} + */ + async listRecordings({ admin_key }) { + const body = { + request: REQUEST_LIST, + }; + if (typeof admin_key === 'string') body.admin_key = admin_key; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.RECORDINGS_LIST) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Re-index the list of recordings. + * + * @param {Object} params + * @param {string} [params.admin_key] - The optional admin key needed for invoking the API + * @returns {Promise} + */ + async updateRecordings({ admin_key }) { + const body = { + request: REQUEST_UPDATE, + }; + if (typeof admin_key === 'string') body.admin_key = admin_key; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Configure a recording session. + * + * @param {Object} params + * @param {number} [params.maxBitrate] - The optional bitrate to enforce via REMB + * @param {number} [params.keyframeInterval] - The optional keyframe interval to enforce, in ms + * @returns {Promise} + */ + async configure({ maxBitrate, keyframeInterval }) { + const body = { + request: REQUEST_CONFIGURE, + }; + if (typeof maxBitrate === 'number') body['video-bitrate-max'] = maxBitrate; + if (typeof keyframeInterval === 'number') body['video-keyframe-interval'] = keyframeInterval; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.CONFIGURED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Start a recording session. + * + * @param {Object} params + * @param {number} [params.id] - The ID to assign to the recording + * @param {string} [params.name] - The short description of the recording + * @param {boolean} [params.is_private] - Flag the recording as private + * @param {string} [params.filename] - Set the base path/filename for the recording + * @param {string} [audiocodec] - Set the audio codec to use in the recording + * @param {string} [videocodec] - Set the video codec to use in the recording + * @param {string} [videoprofile] - Set the video fmtp to use in the recording + * @param {boolean} [params.opusred] - Set whether RED should be negotiated for audio + * @param {boolean} [params.textdata] - In case data channels are negotiated, set whether it should be text (default) or binary data + * @param {boolean} [params.update] - Set to true for renegotiations + * @param {RTCSessionDescription} params.jsep - JSEP offer to be sent to Janus + * @returns {Promise} + */ + async record({ id, name, is_private, filename, audiocodec, videocodec, videoprofile, opusred, textdata, update, jsep }) { + if (!jsep || typeof jsep !== 'object' || jsep && jsep.type !== 'offer') { + const error = new Error('jsep must be an offer'); + return Promise.reject(error); + } + const body = { + request: REQUEST_RECORD, + }; + if (typeof id === 'number') body.id = id; + if (typeof name === 'string') body.name = name; + if (typeof is_private === 'boolean') body.is_private = is_private; + if (typeof filename === 'string') body.filename = filename; + if (typeof audiocodec === 'string') body.audiocodec = audiocodec; + if (typeof videocodec === 'string') body.videocodec = videocodec; + if (typeof videoprofile === 'string') body.videoprofile = videoprofile; + if (typeof opusred === 'boolean') body.opusred = opusred; + if (typeof textdata === 'boolean') body.textdata = textdata; + if (typeof update === 'boolean') body.update = update; + + const response = await this.message(body, jsep); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.RECORDING) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Play an existing recording. + * + * @param {Object} params + * @param {number} params.id - The ID of the recording to replay + * @param {boolean} [params.restart] - Set to true for triggering a renegotiation and an ICE restart + * @returns {Promise} + */ + async play({ id, restart }) { + const body = { + request: REQUEST_PLAY, + id + }; + if (typeof restart === 'boolean') body.restart = restart; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.PREPARING) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Start a playback session. + * + * @param {Object} params + * @param {RTCSessionDescription} params.jsep + * @returns {Promise} + */ + async start({ jsep }) { + if (!jsep || typeof jsep !== 'object' || jsep && jsep.type !== 'answer') { + const error = new Error('jsep must be an answer'); + return Promise.reject(error); + } + + const body = { + request: REQUEST_START, + }; + + const response = await this.message(body, jsep); + const { event, data: evtdata } = this._getPluginEvent(response);; + if (event === PLUGIN_EVENT.PLAYING) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Pauses the current recording session. + * + * @returns {Promise} + */ + async pause() { + const body = { + request: REQUEST_PAUSE, + }; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response);; + if (event === PLUGIN_EVENT.PAUSED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Resumes the current recording session. + * + * @returns {Promise} + */ + async resume() { + const body = { + request: REQUEST_RESUME, + }; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response);; + if (event === PLUGIN_EVENT.RESUMED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Stop the current recording or playback session. + * + * @returns {Promise} + */ + async stop() { + const body = { + request: REQUEST_STOP, + }; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response);; + if (event === PLUGIN_EVENT.STOPPED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + +} + +/** + * The payload of the plugin message (cfr. Janus docs). + * {@link https://janus.conf.meetecho.com/docs/recordplay.html} + * + * @private + * @typedef {Object} RecordPlayData + */ + +/** + * The response event for recordplay recordings request. + * + * @typedef {Object} RECORDPLAY_EVENT_RECORDINGS_LIST + * @property {object[]} list - The list of the recordings as returned by Janus + */ + +/** + * The response event for recordplay update request. + * + * @typedef {Object} RECORDPLAY_EVENT_UPDATE_RESPONSE + */ + +/** + * The response event for record request. + * + * @typedef {Object} RECORDPLAY_EVENT_RECORDING + * @property {number} [id] - The involved recording identifier + * @property {boolean} [is_private] - True if the event mentions a private recording + * @property {RTCSessionDescription} [jsep] - Optional JSEP from Janus + */ + +/** + * The response event for configure request. + * + * @typedef {Object} RECORDPLAY_EVENT_CONFIGURED + * @property {object} [settings] - The current settings as returned by Janus + */ + +/** + * The response event for pause request. + * + * @typedef {Object} RECORDPLAY_EVENT_PAUSED + * @property {number} [id] - The involved recording identifier + */ + +/** + * The response event for resume request. + * + * @typedef {Object} RECORDPLAY_EVENT_RESUMED + * @property {number} [id] - The involved recording identifier + */ + +/** + * The response event for play request. + * + * @typedef {Object} RECORDPLAY_EVENT_PREPARING + * @property {number} [id] - The involved recording identifier + * @property {boolean} [is_private] - True if the event mentions a private recording + * @property {RTCSessionDescription} [jsep] - Optional JSEP from Janus + */ + +/** + * The response event for start request. + * + * @typedef {Object} RECORDPLAY_EVENT_PLAYING + * @property {number} [id] - The involved recording identifier + */ + +/** + * The response event for stop request. + * + * @typedef {Object} RECORDPLAY_EVENT_STOPPED + * @property {number} [id] - The involved recording identifier + * @property {boolean} [is_private] - True if the event mentions a private recording + */ + +/** + * A recordplay slow-link event. + * + * @typedef {Object} RECORDPLAY_EVENT_SLOW_LINK + * @property {string} [media] - Audio or video + * @property {number} [current-bitrate] - The current configured max video bitrate + * @property {boolean} [uplink] - Whether this is an uplink or downlink event + */ + +/** + * A recordplay done event. + * + * @typedef {Object} RECORDPLAY_EVENT_DONE + * @property {number} [id] - The involved recording identifier + * @property {boolean} [is_private] - True if the event mentions a private recording + */ + +/** + * The exported plugin descriptor. + * + * @type {Object} + * @property {string} id - The plugin identifier used when attaching to Janus + * @property {module:recordplay-plugin~RecordPlayHandle} Handle - The custom class implementing the plugin + * @property {Object} EVENT - The events emitted by the plugin + * @property {string} EVENT.RECORDPLAY_SLOW_LINK {@link module:recordplay-plugin~RecordPlayHandle#event:RECORDPLAY_STATUS RECORDPLAY_SLOW_LINK} + * @property {string} EVENT.RECORDPLAY_DONE {@link module:recordplay-plugin~RecordPlayHandle#event:RECORDPLAY_STATUS RECORDPLAY_DONE} + * @property {string} EVENT.RECORDPLAY_ERROR {@link module:recordplay-plugin~RecordPlayHandle#event:RECORDPLAY_ERROR RECORDPLAY_ERROR} + */ +export default { + id: PLUGIN_ID, + Handle: RecordPlayHandle, + + EVENT: { + /** + * Trouble on an active stream. + * + * @event module:recordplay-plugin~RecordPlayHandle#event:RECORDPLAY_SLOW_LINK + * @type {module:recordplay-plugin~RECORDPLAY_EVENT_SLOW_LINK} + */ + RECORDPLAY_SLOW_LINK: PLUGIN_EVENT.SLOW_LINK, + + /** + * A recording/playback session is over. + * + * @event module:recordplay-plugin~RecordPlayHandle#event:RECORDPLAY_DONE + * @type {module:recordplay-plugin~RECORDPLAY_EVENT_DONE} + */ + RECORDPLAY_DONE: PLUGIN_EVENT.DONE, + + /** + * Generic recordplay error. + * + * @event module:recordplay-plugin~RecordPlayHandle#event:RECORDPLAY_ERROR + * @type {Error} + */ + RECORDPLAY_ERROR: PLUGIN_EVENT.ERROR, + }, +}; From d8ce46132b2f3f08834d004eb1661e0522924828 Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Tue, 24 Jun 2025 14:56:23 +0200 Subject: [PATCH 113/114] Add support for TextRoom plugin (Janus API only) (#61) Note: this patch only covers the TextRoom functionality that can be used via Janus API. Room participation is excluded, since that's only available via datachannels messaging, and so out of reach of the library itself. --- README.md | 1 + package.json | 1 + src/plugins/textroom-plugin.js | 531 +++++++++++++++++++++++++++++++++ 3 files changed, 533 insertions(+) create mode 100644 src/plugins/textroom-plugin.js diff --git a/README.md b/README.md index 6966403..316ec01 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ The supported Janus plugins are: - VideoRoom - SIP - Record&Play +- TextRoom (Janus API only) The library is available on [npm](https://www.npmjs.com/package/janode) and the source code is on [github](https://github.com/meetecho/janode). diff --git a/package.json b/package.json index 724bac2..c299f5a 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "./plugins/recordplay": "./src/plugins/recordplay-plugin.js", "./plugins/sip": "./src/plugins/sip-plugin.js", "./plugins/streaming": "./src/plugins/streaming-plugin.js", + "./plugins/textroom": "./src/plugins/textroom-plugin.js", "./plugins/videoroom": "./src/plugins/videoroom-plugin.js" }, "files": [ diff --git a/src/plugins/textroom-plugin.js b/src/plugins/textroom-plugin.js new file mode 100644 index 0000000..6cb30d1 --- /dev/null +++ b/src/plugins/textroom-plugin.js @@ -0,0 +1,531 @@ +'use strict'; + +/** + * This module contains the implementation of the TextRoom plugin (ref. {@link https://janus.conf.meetecho.com/docs/textroom.html}). + * Notice this only covers what's possible via the Janus API: messages only sent via datachannels are not covered by this module. + * @module textroom-plugin + */ + +import Handle from '../handle.js'; + +/* The plugin ID exported in the plugin descriptor */ +const PLUGIN_ID = 'janus.plugin.textroom'; + +/* These are the requests defined for the Janus TextRoom API */ +const REQUEST_SETUP = 'setup'; +const REQUEST_ACK = 'ack'; +const REQUEST_RESTART = 'restart'; +const REQUEST_LIST_ROOMS = 'list'; +const REQUEST_LIST_PARTICIPANTS = 'listparticipants'; +const REQUEST_EXISTS = 'exists'; +const REQUEST_CREATE = 'create'; +const REQUEST_ALLOW = 'allowed'; +const REQUEST_ANNOUNCEMENT = 'announcement'; +const REQUEST_KICK = 'kick'; +const REQUEST_DESTROY = 'destroy'; + +/* These are the events/responses that the Janode plugin will manage */ +/* Some of them will be exported in the plugin descriptor */ +const PLUGIN_EVENT = { + ROOMS_LIST: 'textroom_list', + PARTICIPANTS_LIST: 'textroom_participants_list', + EXISTS: 'textroom_exists', + CREATED: 'textroom_created', + DESTROYED: 'textroom_destroyed', + SUCCESS: 'textroom_success', + ERROR: 'textroom_error', +}; + +/** + * The class implementing the TextRoom plugin (ref. {@link https://janus.conf.meetecho.com/docs/textroom.html}). + * Notice this only covers what's possible via the Janus API: messages only sent via datachannels are not covered by this module.
+ * + * It extends the base Janode Handle class and overrides the base "handleMessage" method.
+ * + * Moreover it defines many methods to support TextRoom operations. + * + * @hideconstructor + * @extends module:handle~Handle + */ +class TextRoomHandle extends Handle { + /** + * Create a Janode TextRoom handle. + * + * @param {module:session~Session} session - A reference to the parent session + * @param {number} id - The handle identifier + */ + constructor(session, id) { + super(session, id); + } + + /** + * The custom "handleMessage" needed for handling TextRoom messages. + * + * @private + * @param {Object} janus_message + * @returns {Object} A falsy value for unhandled events, a truthy value for handled events + */ + handleMessage(janus_message) { + const { plugindata, transaction } = janus_message; + if (plugindata && plugindata.data && plugindata.data.textroom) { + /** + * @type {TextRoomData} + */ + const message_data = plugindata.data; + const { textroom, error, error_code, room } = message_data; + + /* Prepare an object for the output Janode event */ + const janode_event = this._newPluginEvent(janus_message); + + /* Add room information if available */ + if (room) janode_event.data.room = room; + + /* The plugin will emit an event only if the handle does not own the transaction */ + /* That means that a transaction has already been closed or this is an async event */ + const emit = (this.ownsTransaction(transaction) === false); + + switch (textroom) { + + /* success response */ + case 'success': + /* Room exists API */ + if (typeof message_data.exists !== 'undefined') { + janode_event.data.exists = message_data.exists; + janode_event.event = PLUGIN_EVENT.EXISTS; + break; + } + /* Room list API */ + if (typeof message_data.list !== 'undefined') { + janode_event.data.list = message_data.list; + janode_event.event = PLUGIN_EVENT.ROOMS_LIST; + break; + } + /* Participants list API */ + if (typeof message_data.participants !== 'undefined') { + janode_event.data.participants = message_data.participants; + janode_event.event = PLUGIN_EVENT.PARTICIPANTS_LIST; + break; + } + + /* Generic success (might be token disable) */ + if (typeof message_data.allowed !== 'undefined') { + janode_event.data.list = message_data.allowed; + } + /* In this case the "event" field of the Janode event is "success" */ + janode_event.event = PLUGIN_EVENT.SUCCESS; + break; + + /* TextRoom room created */ + case 'created': + janode_event.event = PLUGIN_EVENT.CREATED; + janode_event.data.permanent = message_data.permanent; + break; + + /* TextRoom room destroyed */ + case 'destroyed': + janode_event.event = PLUGIN_EVENT.DESTROYED; + janode_event.data.permanent = message_data.permanent; + break; + + /* Generic event (e.g. errors) */ + case 'event': + /* TextRoom error */ + if (error) { + janode_event.event = PLUGIN_EVENT.ERROR; + janode_event.data = new Error(`${error_code} ${error}`); + /* In case of error, close a transaction */ + this.closeTransactionWithError(transaction, janode_event.data); + break; + } + /* Configuration success for this handle */ + if (typeof message_data.result !== 'undefined') { + if (message_data.result === 'ok') { + janode_event.event = PLUGIN_EVENT.SUCCESS; + } + break; + } + } + + /* The event has been handled */ + if (janode_event.event) { + /* Try to close the transaction */ + this.closeTransactionWithSuccess(transaction, janus_message); + /* If the transaction was not owned, emit the event */ + if (emit) this.emit(janode_event.event, janode_event.data); + return janode_event; + } + } + + /* The event has not been handled, return a falsy value */ + return null; + } + + /*----------*/ + /* USER API */ + /*----------*/ + + /* These are the APIs that users need to work with the textroom plugin */ + + /** + * Setup a datachannel connection. + * + * @returns {Promise} + */ + async setup() { + const body = { + request: REQUEST_SETUP, + }; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Complete the setup or restart of a datachannel connection. + * + * @param {Object} params + * @param {RTCSessionDescription} params.jsep + * @returns {Promise} + */ + async ack(jsep) { + const body = { + request: REQUEST_ACK, + }; + + const response = await this.message(body, jsep); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Restart the setup of a datachannel connection. + * + * @returns {Promise} + */ + async restart() { + const body = { + request: REQUEST_RESTART, + }; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /*----------------*/ + /* Management API */ + /*----------------*/ + + /* These are the APIs needed to manage textroom resources (rooms, forwarders ...) */ + + /** + * List available textroom rooms. + * + * @param {Object} params + * @param {string} [params.admin_key] - The admin key needed for invoking the API + * @returns {Promise} + */ + async list({ admin_key }) { + const body = { + request: REQUEST_LIST_ROOMS, + }; + if (typeof admin_key === 'string') body.admin_key = admin_key; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.ROOMS_LIST) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * List participants inside a room. + * + * @param {Object} params + * @param {number|string} params.room - The room where to execute the list + * @returns {Promise} + */ + async listParticipants({ room, secret }) { + const body = { + request: REQUEST_LIST_PARTICIPANTS, + room, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.PARTICIPANTS_LIST) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Check if a room exists. + * + * @param {Object} params + * @param {number|string} params.room - The involved room + * @returns {Promise} + */ + async exists({ room }) { + const body = { + request: REQUEST_EXISTS, + room, + }; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.EXISTS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Create a textroom room. + * + * @param {Object} params + * @param {number|string} params.room - The room identifier + * @param {string} [params.admin_key] - The admin key needed for invoking the API + * @param {string} [params.description] - A room description + * @param {string} [params.secret] - The secret to be used when managing the room + * @param {string} [params.pin] - The ping needed for joining the room + * @param {boolean} [params.is_private] - Set room as private (hidden in list) + * @param {boolean} [params.history] - Set number of messages to store as a history + * @param {boolean} [params.post] - Set HTTP backend to forward incoming chat messages to + * @param {boolean} [params.permanent] - Set to true to persist the room in the Janus config file + * @returns {Promise} + */ + async create({ room, admin_key, description, secret, pin, is_private, history, post, permanent }) { + const body = { + request: REQUEST_CREATE, + room, + }; + if (typeof admin_key === 'string') body.admin_key = admin_key; + if (typeof description === 'string') body.description = description; + if (typeof secret === 'string') body.secret = secret; + if (typeof pin === 'string') body.pin = pin; + if (typeof is_private === 'boolean') body.is_private = is_private; + if (typeof history === 'number') body.history = history; + if (typeof post === 'string') body.post = post; + if (typeof permanent === 'boolean') body.permanent = permanent; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.CREATED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Edit a textroom token list. + * + * @param {Object} params + * @param {number|string} params.room - The involved room + * @param {"enable"|"disable"|"add"|"remove"} params.action - The action to perform + * @param {string[]} params.list - The list of tokens to add/remove + * @param {string} [params.secret] - The optional secret needed to manage the room + * @returns {Promise} + */ + async allow({ room, action, list, secret }) { + const body = { + request: REQUEST_ALLOW, + room, + action, + }; + if (list && list.length > 0) body.allowed = list; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Send an announcement to a textroom room. + * + * @param {Object} params + * @param {number|string} params.room - The involved room + * @param {string} params.text - The content of the announcement, as text + * @param {string} [params.secret] - The optional secret needed to manage the room + * @returns {Promise} + */ + async announcement({ room, text, secret }) { + const body = { + request: REQUEST_ANNOUNCEMENT, + room, + text, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Kick an user out from a room. + * + * @param {Object} params + * @param {number|string} params.room - The involved room + * @param {string} params.username - The user to kick out + * @param {string} [params.secret] - The optional secret needed for managing the room + * @returns {Promise} + */ + async kick({ room, username, secret }) { + const body = { + request: REQUEST_KICK, + room, + username, + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) { + /* Add data missing from Janus response */ + evtdata.room = body.room; + evtdata.username = body.username; + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + + /** + * Destroy a textroom room. + * + * @param {Object} params + * @param {number|string} params.room - The room to destroy + * @param {boolean} [params.permanent] - Set to true to remove the room from the Janus config file + * @param {string} [params.secret] - The optional secret needed to manage the room + * @returns {Promise} + */ + async destroy({ room, permanent, secret }) { + const body = { + request: REQUEST_DESTROY, + room, + }; + if (typeof permanent === 'boolean') body.permanent = permanent; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.DESTROYED) + return evtdata; + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + +} + +/** + * The payload of the plugin message (cfr. Janus docs). + * {@link https://janus.conf.meetecho.com/docs/textroom.html} + * + * @private + * @typedef {Object} TextRoomData + */ + +/** + * The response event for textroom WebRTC establishment. + * + * @typedef {Object} TEXTROOM_EVENT_SUCCESS + */ + +/** + * The response event for textroom room list request. + * + * @typedef {Object} TEXTROOM_EVENT_ROOMS_LIST + * @property {object[]} list - The list of the rooms as returned by Janus + */ + +/** + * The response event for textroom participants list request. + * + * @typedef {Object} TEXTROOM_EVENT_PARTICIPANTS_LIST + * @property {number|string} room - The involved room + * @property {object[]} participants - The list of participants as returned by Janus + */ + +/** + * The response event for textroom room exists request. + * + * @typedef {Object} TEXTROOM_EVENT_EXISTS + * @property {number|string} room - The involved room + * @property {boolean} exists - True if the rooms exists + */ + +/** + * The response event for textroom room create request. + * + * @typedef {Object} TEXTROOM_EVENT_CREATED + * @property {number|string} room - The created room + * @property {boolean} permanent - True if the room is being persisted in the Janus config file + */ + +/** + * The response event for textroom room destroy request. + * + * @typedef {Object} TEXTROOM_EVENT_DESTROYED + * @property {number|string} room - The destroyed room + * @property {boolean} permanent - True if the room removal is being persisted in the Janus config file + */ + +/** + * The response event for textroom participant kick request. + * + * @typedef {Object} TEXTROOM_EVENT_KICK_RESPONSE + * @property {number|string} room - The involved room + * @property {string} username - The username that has been kicked out + */ + +/** + * The response event for textroom ACL token edit request. + * + * @typedef {Object} TEXTROOM_EVENT_ALLOWED_RESPONSE + * @property {number|string} room - The involved room + * @property {string[]} list - The updated, complete, list of allowed tokens + */ + +/** + * The exported plugin descriptor. + * + * @type {Object} + * @property {string} id - The plugin identifier used when attaching to Janus + * @property {module:textroom-plugin~TextRoomHandle} Handle - The custom class implementing the plugin + * @property {Object} EVENT - The events emitted by the plugin + * @property {string} EVENT.TEXTROOM_ERROR {@link module:textroom-plugin~TextRoomHandle#event:TEXTROOM_ERROR TEXTROOM_ERROR} + */ +export default { + id: PLUGIN_ID, + Handle: TextRoomHandle, + + EVENT: { + /** + * Generic textroom error. + * + * @event module:textroom-plugin~TextRoomHandle#event:TEXTROOM_ERROR + * @type {Error} + */ + TEXTROOM_ERROR: PLUGIN_EVENT.ERROR, + }, +}; From 9473ed6e130431c840b69281be900ccd8a5a1721 Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Tue, 24 Jun 2025 15:01:23 +0200 Subject: [PATCH 114/114] version: bump to v1.8.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 517f2b2..f4d5257 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "janode", - "version": "1.7.5", + "version": "1.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "janode", - "version": "1.7.5", + "version": "1.8.0", "license": "ISC", "dependencies": { "isomorphic-ws": "^4.0.1", diff --git a/package.json b/package.json index c299f5a..83af4c5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "janode", "description": "Meetecho adapter for the Janus WebRTC Server", - "version": "1.7.5", + "version": "1.8.0", "type": "module", "keywords": [ "janus",