├── server
├── .gitignore
├── utils
│ ├── messages.js
│ └── users.js
├── nginx.conf
├── package.json
├── server.js
└── package-lock.json
├── client
├── README.md
├── index.html
├── chat.html
├── js
│ └── main.js
└── css
│ └── style.css
├── screenshots
├── archi.png
├── edge.PNG
└── chrome.PNG
└── README.md
/server/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | nginx
--------------------------------------------------------------------------------
/client/README.md:
--------------------------------------------------------------------------------
1 | ```bash
2 | http-server . --cors --port=5500
3 | ```
--------------------------------------------------------------------------------
/screenshots/archi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmgchess/socketio-redis-pubsub-demo/HEAD/screenshots/archi.png
--------------------------------------------------------------------------------
/screenshots/edge.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmgchess/socketio-redis-pubsub-demo/HEAD/screenshots/edge.PNG
--------------------------------------------------------------------------------
/screenshots/chrome.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmgchess/socketio-redis-pubsub-demo/HEAD/screenshots/chrome.PNG
--------------------------------------------------------------------------------
/server/utils/messages.js:
--------------------------------------------------------------------------------
1 | const moment = require('moment')
2 |
3 | function formatMessage(username, text,port) {
4 | return {
5 | username: username,
6 | text: port +': '+text,
7 | time: moment().format('h:mm a')
8 | }
9 | }
10 |
11 | module.exports = formatMessage;
--------------------------------------------------------------------------------
/server/nginx.conf:
--------------------------------------------------------------------------------
1 | http {
2 |
3 | upstream backend {
4 | hash '$remote_addr $cookie_zzz $http_user_agent';
5 | server 127.0.0.1:1212;
6 | server 127.0.0.1:1213;
7 | }
8 |
9 | server {
10 | listen 80;
11 | root E:\\socket\\server;
12 |
13 | location / {
14 | proxy_pass http://backend;
15 | }
16 | }
17 | }
18 |
19 | events { }
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "socket",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "node server",
8 | "dev": "nodemon server",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@socket.io/redis-adapter": "^7.2.0",
15 | "express": "^4.18.1",
16 | "moment": "^2.29.4",
17 | "redis": "^4.2.0",
18 | "socket.io": "^4.5.1"
19 | },
20 | "devDependencies": {
21 | "nodemon": "^2.0.19"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/server/utils/users.js:
--------------------------------------------------------------------------------
1 | const users = [];
2 |
3 | //join users to chat
4 |
5 | function userJoin(id, username, room) {
6 | const user = { id, username, room };
7 | users.push(user);
8 | return user;
9 | }
10 |
11 | // get current user
12 |
13 | function getCurrentUser(id) {
14 | return users.find((user) => id === user.id);
15 | }
16 |
17 | // user leaves chat
18 | function userLeave(id){
19 | const index = users.findIndex((user) => user.id === id);
20 |
21 | if(index !== -1){
22 | return users.splice(index,1)[0];
23 | }
24 | }
25 |
26 | //get room users
27 | function getRoomUsers(room){
28 | return users.filter((user) => user.room === room);
29 | }
30 |
31 |
32 | module.exports = {
33 | getCurrentUser,
34 | userJoin,
35 | userLeave,
36 | getRoomUsers
37 | };
38 |
--------------------------------------------------------------------------------
/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
13 |
14 |
15 | ChatCord App
16 |
17 |
18 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/client/chat.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | ChatCord App
9 |
10 |
11 |
12 |
16 |
17 |
24 |
25 |
26 |
27 |
28 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/client/js/main.js:
--------------------------------------------------------------------------------
1 | const chatForm = document.getElementById('chat-form');
2 | const chatMessages = document.querySelector('.chat-messages');
3 | const roomName = document.getElementById('room-name');
4 | const userList = document.getElementById('users');
5 |
6 | //Get username and room from url
7 | const { username, room } = Qs.parse(location.search, {
8 | ignoreQueryPrefix: true,
9 | });
10 |
11 | const socket = io('http://localhost:80');
12 | // const socket = io();
13 |
14 | socket.emit('joinRoom', { username, room });
15 |
16 | //get room and users
17 | socket.on('roomUsers', ({ room, users }) => {
18 | outputRoomName(room);
19 | outputUsers(users);
20 | });
21 |
22 | //message from server
23 | socket.on('message', ({ username, text, time }) => {
24 | console.log({ username, text, time });
25 | outputMessage(username, text, time);
26 |
27 | //scroll down
28 | chatMessages.scrollTop = chatMessages.scrollHeight;
29 | });
30 |
31 | //Message-submit
32 | chatForm.addEventListener('submit', (e) => {
33 | e.preventDefault();
34 |
35 | ///Get message text
36 | const msg = e.target.elements.msg.value;
37 |
38 | //Emit message to server
39 | socket.emit('chatMessage', msg);
40 |
41 | //clear input
42 | e.target.elements.msg.value = '';
43 | e.target.elements.msg.focus();
44 | });
45 |
46 | //output msg to dom
47 | function outputMessage(username, text, time) {
48 | const div = document.createElement('div');
49 | div.classList.add('message');
50 | div.innerHTML = ` ${username} ${time}
51 |
52 | ${text}
53 |
`;
54 | document.querySelector('.chat-messages').appendChild(div);
55 | }
56 |
57 | //add room name to dom
58 | function outputRoomName(room) {
59 | roomName.innerText = room;
60 | }
61 |
62 | //add users to dom
63 | function outputUsers(users) {
64 | userList.innerHTML = `
65 | ${users.map((user) => `${user.username}`).join('')}
66 | `;
67 | }
68 |
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const express = require('express');
3 |
4 | const { createClient } = require('redis');
5 | const { createAdapter } = require('@socket.io/redis-adapter');
6 | const socketio = require('socket.io');
7 |
8 | const formatMessage = require('./utils/messages');
9 | const {
10 | userJoin,
11 | getCurrentUser,
12 | userLeave,
13 | getRoomUsers,
14 | } = require('./utils/users');
15 |
16 | const PORT = process.env.PORT;
17 |
18 | const app = express();
19 | const server = http.createServer(app);
20 |
21 | //https://socket.io/docs/v4/using-multiple-nodes/#enabling-sticky-session
22 | const io = socketio(server, {
23 | cors: {
24 | origin: ['http://127.0.0.1:5500'],
25 | methods: ['GET', 'POST'],
26 | transports: ['websocket', 'polling'],
27 | credentials: true,
28 | },
29 | });
30 |
31 | const url = 'redis://127.0.0.1:6379';
32 | pubClient = createClient({ url });
33 | subClient = pubClient.duplicate();
34 |
35 | //https://socket.io/docs/v4/redis-adapter/#usage
36 | const initPubSub = async () => {
37 | await Promise.all([pubClient.connect(), subClient.connect()]);
38 | io.adapter(createAdapter(pubClient, subClient));
39 | };
40 |
41 | initPubSub();
42 |
43 | const BOT_NAME = 'Chatcord-BOT';
44 |
45 | //Run when client connects
46 | io.on('connection', (socket) => {
47 | console.log(`connected to ${PORT}`);
48 | socket.on('joinRoom', ({ username, room }) => {
49 | console.log(`connected to room ${PORT}`);
50 | const user = userJoin(socket.id, username, room);
51 |
52 | socket.join(user.room);
53 |
54 | //Welcome current user
55 | socket.emit(
56 | 'message',
57 | formatMessage(BOT_NAME, 'Welcome to chatcord!', PORT)
58 | );
59 |
60 | //broadcase when a user connects
61 | socket.broadcast
62 | .to(user.room)
63 | .emit(
64 | 'message',
65 | formatMessage(BOT_NAME, `${user.username} has joined the chat`, PORT)
66 | );
67 |
68 | //send users and room info
69 | io.to(user.room).emit('roomUsers', {
70 | room: user.room,
71 | users: getRoomUsers(user.room),
72 | });
73 | });
74 |
75 | //Listen for chatMessage
76 | socket.on('chatMessage', (msg) => {
77 | const user = getCurrentUser(socket.id);
78 | console.log(`Chat Message: ${msg} from ${user.username} from PORT ${PORT}`);
79 | io.to(user.room).emit('message', formatMessage(user.username, msg, PORT));
80 | });
81 |
82 | socket.on('disconnect', () => {
83 | const user = userLeave(socket.id);
84 | if (user) {
85 | io.to(user.room).emit(
86 | 'message',
87 | formatMessage(BOT_NAME, `${user.username} has left the chat`, PORT)
88 | );
89 |
90 | //send users and room info
91 | io.to(user.room).emit('roomUsers', {
92 | room: user.room,
93 | users: getRoomUsers(user.room),
94 | });
95 | }
96 | });
97 | });
98 |
99 | server.listen(PORT, () => console.log(`Server running on port ${PORT}`));
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | **Prerequisites**
3 |
4 | - [Realtime Chat With Users & Rooms - Socket.io, Node & Express](https://www.youtube.com/watch?v=jD7FnbI76Hg "Realtime Chat With Users & Rooms - Socket.io, Node & Express")
5 | - [REPO - bradtraversy/chatcord](https://github.com/bradtraversy/chatcord)
6 |
7 | **Additional helpful resources**
8 |
9 | - [Scaling Websockets with Redis, HAProxy and Node JS - High-availability Group Chat Application](https://www.youtube.com/watch?v=gzIcGhJC8hA "Scaling Websockets with Redis, HAProxy and Node JS - High-availability Group Chat Application")
10 | - [Load Balancing NodeJS applications using NginX](https://www.youtube.com/watch?v=eYXXEWVTZpk "Load Balancing NodeJS applications using NginX")
11 | - [Socket.IO Docs - Using multiple nodes](https://socket.io/docs/v4/using-multiple-nodes/)
12 | - [Socket.IO Docs - Adapters](https://socket.io/docs/v4/adapter/)
13 | - [Socket.IO Docs - Redis adapter](https://socket.io/docs/v4/redis-adapter/)
14 |
15 | **Additional Tools**
16 |
17 | - [nginx](http://nginx.org/en/download.html)
18 | - [Redis](https://redis.io/download/)
19 | - [Node.js](https://nodejs.org/en/download/) v14+
20 | - [http-server](https://www.npmjs.com/package/http-server)
21 |
22 | [Here](https://kasunprageethdissanayake.medium.com/installing-redis-x64-3-2-100-on-windows-and-running-redis-server-94db3a98ae3d) is a MSI installer I found for Redis.
23 |
24 | **Setup**
25 |
26 | 1. Clone repository
27 | 2. cd into `server` and `npm install`
28 |
29 |
30 | **Nginx conf**
31 |
32 | ```bash
33 | http {
34 |
35 | upstream backend {
36 | hash '$remote_addr $cookie_zzz $http_user_agent';
37 | server 127.0.0.1:1212;
38 | server 127.0.0.1:1213;
39 | }
40 |
41 | server {
42 | listen 80;
43 | root E:\\socket\\server;
44 |
45 | location / {
46 | proxy_pass http://backend;
47 | }
48 | }
49 | }
50 |
51 | events { }
52 |
53 | ```
54 | https://stackoverflow.com/questions/59124543/nginx-not-loadbalancing-in-case-of-ip-hash
55 |
56 | **Running client**
57 | 1. cd into`client`
58 | 2. run `http-server . --cors --port=5500`
59 |
60 | **Running server**
61 |
62 | 1. cd into `server` and open 2 terminals for the same directory
63 | 2. Set 2 different ports ( ex: `export PORT=1212` in one terminal and `export PORT=1213` in the other)
64 | 3. Start nginx with the given configuration
65 | 4. `npm start` the server on both terminals
66 |
67 | Now Server 1 will be started on `PORT=1212` and Server 2 on `PORT=1213` and the Client on `PORT=5500`. Two servers will be load balanced using nginx on `PORT=80` so the client will be directed to either Server 1 or 2 when it hits Port 80. Hash based load balancing is enabled (to achieve stickiness) since nginx open source doesn't allow cookie based load balancing. Go to http://127.0.0.1:5500/ with 2 browsers (Edge and Chrome for example) then the 2 instances will be connected to Server 1 and 2 respectively.
68 | Redis will act as a [PubSub](https://redis.io/docs/manual/pubsub/) mechanism and is enabled using [Socket.IO Redis Adapter](https://socket.io/docs/v4/redis-adapter/).
69 | **NOTE: Redis adapter will not store anything, it will only do PubSub.**
70 | If you want you can store data in Redis as well.
71 |
72 |
73 | 
74 |
75 | 
76 | 
77 |
--------------------------------------------------------------------------------
/client/css/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
2 |
3 | :root {
4 | --dark-color-a: #667aff;
5 | --dark-color-b: #7386ff;
6 | --light-color: #e6e9ff;
7 | --success-color: #5cb85c;
8 | --error-color: #d9534f;
9 | }
10 |
11 | * {
12 | box-sizing: border-box;
13 | margin: 0;
14 | padding: 0;
15 | }
16 |
17 | body {
18 | font-family: 'Roboto', sans-serif;
19 | font-size: 16px;
20 | background: var(--light-color);
21 | margin: 20px;
22 | }
23 |
24 | ul {
25 | list-style: none;
26 | }
27 |
28 | a {
29 | text-decoration: none;
30 | }
31 |
32 | .btn {
33 | cursor: pointer;
34 | padding: 5px 15px;
35 | background: var(--light-color);
36 | color: var(--dark-color-a);
37 | border: 0;
38 | font-size: 17px;
39 | }
40 |
41 | /* Chat Page */
42 |
43 | .chat-container {
44 | max-width: 1100px;
45 | background: #fff;
46 | margin: 30px auto;
47 | overflow: hidden;
48 | }
49 |
50 | .chat-header {
51 | background: var(--dark-color-a);
52 | color: #fff;
53 | border-top-left-radius: 5px;
54 | border-top-right-radius: 5px;
55 | padding: 15px;
56 | display: flex;
57 | align-items: center;
58 | justify-content: space-between;
59 | }
60 |
61 | .chat-main {
62 | display: grid;
63 | grid-template-columns: 1fr 3fr;
64 | }
65 |
66 | .chat-sidebar {
67 | background: var(--dark-color-b);
68 | color: #fff;
69 | padding: 20px 20px 60px;
70 | overflow-y: scroll;
71 | }
72 |
73 | .chat-sidebar h2 {
74 | font-size: 20px;
75 | background: rgba(0, 0, 0, 0.1);
76 | padding: 10px;
77 | margin-bottom: 20px;
78 | }
79 |
80 | .chat-sidebar h3 {
81 | margin-bottom: 15px;
82 | }
83 |
84 | .chat-sidebar ul li {
85 | padding: 10px 0;
86 | }
87 |
88 | .chat-messages {
89 | padding: 30px;
90 | max-height: 500px;
91 | overflow-y: scroll;
92 | }
93 |
94 | .chat-messages .message {
95 | padding: 10px;
96 | margin-bottom: 15px;
97 | background-color: var(--light-color);
98 | border-radius: 5px;
99 | }
100 |
101 | .chat-messages .message .meta {
102 | font-size: 15px;
103 | font-weight: bold;
104 | color: var(--dark-color-b);
105 | opacity: 0.7;
106 | margin-bottom: 7px;
107 | }
108 |
109 | .chat-messages .message .meta span {
110 | color: #777;
111 | }
112 |
113 | .chat-form-container {
114 | padding: 20px 30px;
115 | background-color: var(--dark-color-a);
116 | }
117 |
118 | .chat-form-container form {
119 | display: flex;
120 | }
121 |
122 | .chat-form-container input[type='text'] {
123 | font-size: 16px;
124 | padding: 5px;
125 | height: 40px;
126 | flex: 1;
127 | }
128 |
129 | /* Join Page */
130 | .join-container {
131 | max-width: 500px;
132 | margin: 80px auto;
133 | color: #fff;
134 | }
135 |
136 | .join-header {
137 | text-align: center;
138 | padding: 20px;
139 | background: var(--dark-color-a);
140 | border-top-left-radius: 5px;
141 | border-top-right-radius: 5px;
142 | }
143 |
144 | .join-main {
145 | padding: 30px 40px;
146 | background: var(--dark-color-b);
147 | }
148 |
149 | .join-main p {
150 | margin-bottom: 20px;
151 | }
152 |
153 | .join-main .form-control {
154 | margin-bottom: 20px;
155 | }
156 |
157 | .join-main label {
158 | display: block;
159 | margin-bottom: 5px;
160 | }
161 |
162 | .join-main input[type='text'] {
163 | font-size: 16px;
164 | padding: 5px;
165 | height: 40px;
166 | width: 100%;
167 | }
168 |
169 | .join-main select {
170 | font-size: 16px;
171 | padding: 5px;
172 | height: 40px;
173 | width: 100%;
174 | }
175 |
176 | .join-main .btn {
177 | margin-top: 20px;
178 | width: 100%;
179 | }
180 |
181 | @media (max-width: 700px) {
182 | .chat-main {
183 | display: block;
184 | }
185 |
186 | .chat-sidebar {
187 | display: none;
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/server/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "socket",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@redis/bloom": {
8 | "version": "1.0.2",
9 | "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz",
10 | "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw=="
11 | },
12 | "@redis/client": {
13 | "version": "1.2.0",
14 | "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.2.0.tgz",
15 | "integrity": "sha512-a8Nlw5fv2EIAFJxTDSSDVUT7yfBGpZO96ybZXzQpgkyLg/dxtQ1uiwTc0EGfzg1mrPjZokeBSEGTbGXekqTNOg==",
16 | "requires": {
17 | "cluster-key-slot": "1.1.0",
18 | "generic-pool": "3.8.2",
19 | "yallist": "4.0.0"
20 | }
21 | },
22 | "@redis/graph": {
23 | "version": "1.0.1",
24 | "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz",
25 | "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ=="
26 | },
27 | "@redis/json": {
28 | "version": "1.0.3",
29 | "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.3.tgz",
30 | "integrity": "sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q=="
31 | },
32 | "@redis/search": {
33 | "version": "1.0.6",
34 | "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.0.6.tgz",
35 | "integrity": "sha512-pP+ZQRis5P21SD6fjyCeLcQdps+LuTzp2wdUbzxEmNhleighDDTD5ck8+cYof+WLec4csZX7ks+BuoMw0RaZrA=="
36 | },
37 | "@redis/time-series": {
38 | "version": "1.0.3",
39 | "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz",
40 | "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA=="
41 | },
42 | "@socket.io/redis-adapter": {
43 | "version": "7.2.0",
44 | "resolved": "https://registry.npmjs.org/@socket.io/redis-adapter/-/redis-adapter-7.2.0.tgz",
45 | "integrity": "sha512-/r6oF6Myz0K9uatB/pfCi0BhKg/KRMh1OokrqcjlNz6aq40WiXdFLRbHJQuwGHq/KvB+D6141K+IynbVxZGvhw==",
46 | "requires": {
47 | "debug": "~4.3.1",
48 | "notepack.io": "~2.2.0",
49 | "socket.io-adapter": "^2.4.0",
50 | "uid2": "0.0.3"
51 | }
52 | },
53 | "@types/component-emitter": {
54 | "version": "1.2.11",
55 | "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz",
56 | "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ=="
57 | },
58 | "@types/cookie": {
59 | "version": "0.4.1",
60 | "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
61 | "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
62 | },
63 | "@types/cors": {
64 | "version": "2.8.12",
65 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
66 | "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
67 | },
68 | "@types/node": {
69 | "version": "18.6.1",
70 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz",
71 | "integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg=="
72 | },
73 | "abbrev": {
74 | "version": "1.1.1",
75 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
76 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
77 | "dev": true
78 | },
79 | "accepts": {
80 | "version": "1.3.8",
81 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
82 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
83 | "requires": {
84 | "mime-types": "~2.1.34",
85 | "negotiator": "0.6.3"
86 | }
87 | },
88 | "anymatch": {
89 | "version": "3.1.2",
90 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
91 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
92 | "dev": true,
93 | "requires": {
94 | "normalize-path": "^3.0.0",
95 | "picomatch": "^2.0.4"
96 | }
97 | },
98 | "array-flatten": {
99 | "version": "1.1.1",
100 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
101 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
102 | },
103 | "balanced-match": {
104 | "version": "1.0.2",
105 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
106 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
107 | "dev": true
108 | },
109 | "base64id": {
110 | "version": "2.0.0",
111 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
112 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
113 | },
114 | "binary-extensions": {
115 | "version": "2.2.0",
116 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
117 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
118 | "dev": true
119 | },
120 | "body-parser": {
121 | "version": "1.20.0",
122 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
123 | "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
124 | "requires": {
125 | "bytes": "3.1.2",
126 | "content-type": "~1.0.4",
127 | "debug": "2.6.9",
128 | "depd": "2.0.0",
129 | "destroy": "1.2.0",
130 | "http-errors": "2.0.0",
131 | "iconv-lite": "0.4.24",
132 | "on-finished": "2.4.1",
133 | "qs": "6.10.3",
134 | "raw-body": "2.5.1",
135 | "type-is": "~1.6.18",
136 | "unpipe": "1.0.0"
137 | },
138 | "dependencies": {
139 | "debug": {
140 | "version": "2.6.9",
141 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
142 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
143 | "requires": {
144 | "ms": "2.0.0"
145 | }
146 | },
147 | "ms": {
148 | "version": "2.0.0",
149 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
150 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
151 | }
152 | }
153 | },
154 | "brace-expansion": {
155 | "version": "1.1.11",
156 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
157 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
158 | "dev": true,
159 | "requires": {
160 | "balanced-match": "^1.0.0",
161 | "concat-map": "0.0.1"
162 | }
163 | },
164 | "braces": {
165 | "version": "3.0.2",
166 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
167 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
168 | "dev": true,
169 | "requires": {
170 | "fill-range": "^7.0.1"
171 | }
172 | },
173 | "bytes": {
174 | "version": "3.1.2",
175 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
176 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
177 | },
178 | "call-bind": {
179 | "version": "1.0.2",
180 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
181 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
182 | "requires": {
183 | "function-bind": "^1.1.1",
184 | "get-intrinsic": "^1.0.2"
185 | }
186 | },
187 | "chokidar": {
188 | "version": "3.5.3",
189 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
190 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
191 | "dev": true,
192 | "requires": {
193 | "anymatch": "~3.1.2",
194 | "braces": "~3.0.2",
195 | "fsevents": "~2.3.2",
196 | "glob-parent": "~5.1.2",
197 | "is-binary-path": "~2.1.0",
198 | "is-glob": "~4.0.1",
199 | "normalize-path": "~3.0.0",
200 | "readdirp": "~3.6.0"
201 | }
202 | },
203 | "cluster-key-slot": {
204 | "version": "1.1.0",
205 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz",
206 | "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw=="
207 | },
208 | "component-emitter": {
209 | "version": "1.3.0",
210 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
211 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
212 | },
213 | "concat-map": {
214 | "version": "0.0.1",
215 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
216 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
217 | "dev": true
218 | },
219 | "content-disposition": {
220 | "version": "0.5.4",
221 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
222 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
223 | "requires": {
224 | "safe-buffer": "5.2.1"
225 | }
226 | },
227 | "content-type": {
228 | "version": "1.0.4",
229 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
230 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
231 | },
232 | "cookie": {
233 | "version": "0.5.0",
234 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
235 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
236 | },
237 | "cookie-signature": {
238 | "version": "1.0.6",
239 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
240 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
241 | },
242 | "cors": {
243 | "version": "2.8.5",
244 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
245 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
246 | "requires": {
247 | "object-assign": "^4",
248 | "vary": "^1"
249 | }
250 | },
251 | "debug": {
252 | "version": "4.3.4",
253 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
254 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
255 | "requires": {
256 | "ms": "2.1.2"
257 | }
258 | },
259 | "depd": {
260 | "version": "2.0.0",
261 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
262 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
263 | },
264 | "destroy": {
265 | "version": "1.2.0",
266 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
267 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
268 | },
269 | "ee-first": {
270 | "version": "1.1.1",
271 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
272 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
273 | },
274 | "encodeurl": {
275 | "version": "1.0.2",
276 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
277 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
278 | },
279 | "engine.io": {
280 | "version": "6.2.0",
281 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz",
282 | "integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==",
283 | "requires": {
284 | "@types/cookie": "^0.4.1",
285 | "@types/cors": "^2.8.12",
286 | "@types/node": ">=10.0.0",
287 | "accepts": "~1.3.4",
288 | "base64id": "2.0.0",
289 | "cookie": "~0.4.1",
290 | "cors": "~2.8.5",
291 | "debug": "~4.3.1",
292 | "engine.io-parser": "~5.0.3",
293 | "ws": "~8.2.3"
294 | },
295 | "dependencies": {
296 | "cookie": {
297 | "version": "0.4.2",
298 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
299 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
300 | }
301 | }
302 | },
303 | "engine.io-parser": {
304 | "version": "5.0.4",
305 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
306 | "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg=="
307 | },
308 | "escape-html": {
309 | "version": "1.0.3",
310 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
311 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
312 | },
313 | "etag": {
314 | "version": "1.8.1",
315 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
316 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
317 | },
318 | "express": {
319 | "version": "4.18.1",
320 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
321 | "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
322 | "requires": {
323 | "accepts": "~1.3.8",
324 | "array-flatten": "1.1.1",
325 | "body-parser": "1.20.0",
326 | "content-disposition": "0.5.4",
327 | "content-type": "~1.0.4",
328 | "cookie": "0.5.0",
329 | "cookie-signature": "1.0.6",
330 | "debug": "2.6.9",
331 | "depd": "2.0.0",
332 | "encodeurl": "~1.0.2",
333 | "escape-html": "~1.0.3",
334 | "etag": "~1.8.1",
335 | "finalhandler": "1.2.0",
336 | "fresh": "0.5.2",
337 | "http-errors": "2.0.0",
338 | "merge-descriptors": "1.0.1",
339 | "methods": "~1.1.2",
340 | "on-finished": "2.4.1",
341 | "parseurl": "~1.3.3",
342 | "path-to-regexp": "0.1.7",
343 | "proxy-addr": "~2.0.7",
344 | "qs": "6.10.3",
345 | "range-parser": "~1.2.1",
346 | "safe-buffer": "5.2.1",
347 | "send": "0.18.0",
348 | "serve-static": "1.15.0",
349 | "setprototypeof": "1.2.0",
350 | "statuses": "2.0.1",
351 | "type-is": "~1.6.18",
352 | "utils-merge": "1.0.1",
353 | "vary": "~1.1.2"
354 | },
355 | "dependencies": {
356 | "debug": {
357 | "version": "2.6.9",
358 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
359 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
360 | "requires": {
361 | "ms": "2.0.0"
362 | }
363 | },
364 | "ms": {
365 | "version": "2.0.0",
366 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
367 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
368 | }
369 | }
370 | },
371 | "fill-range": {
372 | "version": "7.0.1",
373 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
374 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
375 | "dev": true,
376 | "requires": {
377 | "to-regex-range": "^5.0.1"
378 | }
379 | },
380 | "finalhandler": {
381 | "version": "1.2.0",
382 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
383 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
384 | "requires": {
385 | "debug": "2.6.9",
386 | "encodeurl": "~1.0.2",
387 | "escape-html": "~1.0.3",
388 | "on-finished": "2.4.1",
389 | "parseurl": "~1.3.3",
390 | "statuses": "2.0.1",
391 | "unpipe": "~1.0.0"
392 | },
393 | "dependencies": {
394 | "debug": {
395 | "version": "2.6.9",
396 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
397 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
398 | "requires": {
399 | "ms": "2.0.0"
400 | }
401 | },
402 | "ms": {
403 | "version": "2.0.0",
404 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
405 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
406 | }
407 | }
408 | },
409 | "forwarded": {
410 | "version": "0.2.0",
411 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
412 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
413 | },
414 | "fresh": {
415 | "version": "0.5.2",
416 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
417 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
418 | },
419 | "fsevents": {
420 | "version": "2.3.2",
421 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
422 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
423 | "dev": true,
424 | "optional": true
425 | },
426 | "function-bind": {
427 | "version": "1.1.1",
428 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
429 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
430 | },
431 | "generic-pool": {
432 | "version": "3.8.2",
433 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz",
434 | "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg=="
435 | },
436 | "get-intrinsic": {
437 | "version": "1.1.2",
438 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
439 | "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
440 | "requires": {
441 | "function-bind": "^1.1.1",
442 | "has": "^1.0.3",
443 | "has-symbols": "^1.0.3"
444 | }
445 | },
446 | "glob-parent": {
447 | "version": "5.1.2",
448 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
449 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
450 | "dev": true,
451 | "requires": {
452 | "is-glob": "^4.0.1"
453 | }
454 | },
455 | "has": {
456 | "version": "1.0.3",
457 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
458 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
459 | "requires": {
460 | "function-bind": "^1.1.1"
461 | }
462 | },
463 | "has-flag": {
464 | "version": "3.0.0",
465 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
466 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
467 | "dev": true
468 | },
469 | "has-symbols": {
470 | "version": "1.0.3",
471 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
472 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
473 | },
474 | "http-errors": {
475 | "version": "2.0.0",
476 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
477 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
478 | "requires": {
479 | "depd": "2.0.0",
480 | "inherits": "2.0.4",
481 | "setprototypeof": "1.2.0",
482 | "statuses": "2.0.1",
483 | "toidentifier": "1.0.1"
484 | }
485 | },
486 | "iconv-lite": {
487 | "version": "0.4.24",
488 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
489 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
490 | "requires": {
491 | "safer-buffer": ">= 2.1.2 < 3"
492 | }
493 | },
494 | "ignore-by-default": {
495 | "version": "1.0.1",
496 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
497 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
498 | "dev": true
499 | },
500 | "inherits": {
501 | "version": "2.0.4",
502 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
503 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
504 | },
505 | "ipaddr.js": {
506 | "version": "1.9.1",
507 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
508 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
509 | },
510 | "is-binary-path": {
511 | "version": "2.1.0",
512 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
513 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
514 | "dev": true,
515 | "requires": {
516 | "binary-extensions": "^2.0.0"
517 | }
518 | },
519 | "is-extglob": {
520 | "version": "2.1.1",
521 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
522 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
523 | "dev": true
524 | },
525 | "is-glob": {
526 | "version": "4.0.3",
527 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
528 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
529 | "dev": true,
530 | "requires": {
531 | "is-extglob": "^2.1.1"
532 | }
533 | },
534 | "is-number": {
535 | "version": "7.0.0",
536 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
537 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
538 | "dev": true
539 | },
540 | "media-typer": {
541 | "version": "0.3.0",
542 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
543 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
544 | },
545 | "merge-descriptors": {
546 | "version": "1.0.1",
547 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
548 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
549 | },
550 | "methods": {
551 | "version": "1.1.2",
552 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
553 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
554 | },
555 | "mime": {
556 | "version": "1.6.0",
557 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
558 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
559 | },
560 | "mime-db": {
561 | "version": "1.52.0",
562 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
563 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
564 | },
565 | "mime-types": {
566 | "version": "2.1.35",
567 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
568 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
569 | "requires": {
570 | "mime-db": "1.52.0"
571 | }
572 | },
573 | "minimatch": {
574 | "version": "3.1.2",
575 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
576 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
577 | "dev": true,
578 | "requires": {
579 | "brace-expansion": "^1.1.7"
580 | }
581 | },
582 | "moment": {
583 | "version": "2.29.4",
584 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
585 | "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
586 | },
587 | "ms": {
588 | "version": "2.1.2",
589 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
590 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
591 | },
592 | "negotiator": {
593 | "version": "0.6.3",
594 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
595 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
596 | },
597 | "nodemon": {
598 | "version": "2.0.19",
599 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.19.tgz",
600 | "integrity": "sha512-4pv1f2bMDj0Eeg/MhGqxrtveeQ5/G/UVe9iO6uTZzjnRluSA4PVWf8CW99LUPwGB3eNIA7zUFoP77YuI7hOc0A==",
601 | "dev": true,
602 | "requires": {
603 | "chokidar": "^3.5.2",
604 | "debug": "^3.2.7",
605 | "ignore-by-default": "^1.0.1",
606 | "minimatch": "^3.0.4",
607 | "pstree.remy": "^1.1.8",
608 | "semver": "^5.7.1",
609 | "simple-update-notifier": "^1.0.7",
610 | "supports-color": "^5.5.0",
611 | "touch": "^3.1.0",
612 | "undefsafe": "^2.0.5"
613 | },
614 | "dependencies": {
615 | "debug": {
616 | "version": "3.2.7",
617 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
618 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
619 | "dev": true,
620 | "requires": {
621 | "ms": "^2.1.1"
622 | }
623 | }
624 | }
625 | },
626 | "nopt": {
627 | "version": "1.0.10",
628 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
629 | "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
630 | "dev": true,
631 | "requires": {
632 | "abbrev": "1"
633 | }
634 | },
635 | "normalize-path": {
636 | "version": "3.0.0",
637 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
638 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
639 | "dev": true
640 | },
641 | "notepack.io": {
642 | "version": "2.2.0",
643 | "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-2.2.0.tgz",
644 | "integrity": "sha512-9b5w3t5VSH6ZPosoYnyDONnUTF8o0UkBw7JLA6eBlYJWyGT1Q3vQa8Hmuj1/X6RYvHjjygBDgw6fJhe0JEojfw=="
645 | },
646 | "object-assign": {
647 | "version": "4.1.1",
648 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
649 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
650 | },
651 | "object-inspect": {
652 | "version": "1.12.2",
653 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
654 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
655 | },
656 | "on-finished": {
657 | "version": "2.4.1",
658 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
659 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
660 | "requires": {
661 | "ee-first": "1.1.1"
662 | }
663 | },
664 | "parseurl": {
665 | "version": "1.3.3",
666 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
667 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
668 | },
669 | "path-to-regexp": {
670 | "version": "0.1.7",
671 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
672 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
673 | },
674 | "picomatch": {
675 | "version": "2.3.1",
676 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
677 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
678 | "dev": true
679 | },
680 | "proxy-addr": {
681 | "version": "2.0.7",
682 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
683 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
684 | "requires": {
685 | "forwarded": "0.2.0",
686 | "ipaddr.js": "1.9.1"
687 | }
688 | },
689 | "pstree.remy": {
690 | "version": "1.1.8",
691 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
692 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
693 | "dev": true
694 | },
695 | "qs": {
696 | "version": "6.10.3",
697 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
698 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
699 | "requires": {
700 | "side-channel": "^1.0.4"
701 | }
702 | },
703 | "range-parser": {
704 | "version": "1.2.1",
705 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
706 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
707 | },
708 | "raw-body": {
709 | "version": "2.5.1",
710 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
711 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
712 | "requires": {
713 | "bytes": "3.1.2",
714 | "http-errors": "2.0.0",
715 | "iconv-lite": "0.4.24",
716 | "unpipe": "1.0.0"
717 | }
718 | },
719 | "readdirp": {
720 | "version": "3.6.0",
721 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
722 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
723 | "dev": true,
724 | "requires": {
725 | "picomatch": "^2.2.1"
726 | }
727 | },
728 | "redis": {
729 | "version": "4.2.0",
730 | "resolved": "https://registry.npmjs.org/redis/-/redis-4.2.0.tgz",
731 | "integrity": "sha512-bCR0gKVhIXFg8zCQjXEANzgI01DDixtPZgIUZHBCmwqixnu+MK3Tb2yqGjh+HCLASQVVgApiwhNkv+FoedZOGQ==",
732 | "requires": {
733 | "@redis/bloom": "1.0.2",
734 | "@redis/client": "1.2.0",
735 | "@redis/graph": "1.0.1",
736 | "@redis/json": "1.0.3",
737 | "@redis/search": "1.0.6",
738 | "@redis/time-series": "1.0.3"
739 | }
740 | },
741 | "safe-buffer": {
742 | "version": "5.2.1",
743 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
744 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
745 | },
746 | "safer-buffer": {
747 | "version": "2.1.2",
748 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
749 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
750 | },
751 | "semver": {
752 | "version": "5.7.1",
753 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
754 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
755 | "dev": true
756 | },
757 | "send": {
758 | "version": "0.18.0",
759 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
760 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
761 | "requires": {
762 | "debug": "2.6.9",
763 | "depd": "2.0.0",
764 | "destroy": "1.2.0",
765 | "encodeurl": "~1.0.2",
766 | "escape-html": "~1.0.3",
767 | "etag": "~1.8.1",
768 | "fresh": "0.5.2",
769 | "http-errors": "2.0.0",
770 | "mime": "1.6.0",
771 | "ms": "2.1.3",
772 | "on-finished": "2.4.1",
773 | "range-parser": "~1.2.1",
774 | "statuses": "2.0.1"
775 | },
776 | "dependencies": {
777 | "debug": {
778 | "version": "2.6.9",
779 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
780 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
781 | "requires": {
782 | "ms": "2.0.0"
783 | },
784 | "dependencies": {
785 | "ms": {
786 | "version": "2.0.0",
787 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
788 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
789 | }
790 | }
791 | },
792 | "ms": {
793 | "version": "2.1.3",
794 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
795 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
796 | }
797 | }
798 | },
799 | "serve-static": {
800 | "version": "1.15.0",
801 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
802 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
803 | "requires": {
804 | "encodeurl": "~1.0.2",
805 | "escape-html": "~1.0.3",
806 | "parseurl": "~1.3.3",
807 | "send": "0.18.0"
808 | }
809 | },
810 | "setprototypeof": {
811 | "version": "1.2.0",
812 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
813 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
814 | },
815 | "side-channel": {
816 | "version": "1.0.4",
817 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
818 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
819 | "requires": {
820 | "call-bind": "^1.0.0",
821 | "get-intrinsic": "^1.0.2",
822 | "object-inspect": "^1.9.0"
823 | }
824 | },
825 | "simple-update-notifier": {
826 | "version": "1.0.7",
827 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz",
828 | "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==",
829 | "dev": true,
830 | "requires": {
831 | "semver": "~7.0.0"
832 | },
833 | "dependencies": {
834 | "semver": {
835 | "version": "7.0.0",
836 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
837 | "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
838 | "dev": true
839 | }
840 | }
841 | },
842 | "socket.io": {
843 | "version": "4.5.1",
844 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz",
845 | "integrity": "sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==",
846 | "requires": {
847 | "accepts": "~1.3.4",
848 | "base64id": "~2.0.0",
849 | "debug": "~4.3.2",
850 | "engine.io": "~6.2.0",
851 | "socket.io-adapter": "~2.4.0",
852 | "socket.io-parser": "~4.0.4"
853 | }
854 | },
855 | "socket.io-adapter": {
856 | "version": "2.4.0",
857 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz",
858 | "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg=="
859 | },
860 | "socket.io-parser": {
861 | "version": "4.0.5",
862 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz",
863 | "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==",
864 | "requires": {
865 | "@types/component-emitter": "^1.2.10",
866 | "component-emitter": "~1.3.0",
867 | "debug": "~4.3.1"
868 | }
869 | },
870 | "statuses": {
871 | "version": "2.0.1",
872 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
873 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
874 | },
875 | "supports-color": {
876 | "version": "5.5.0",
877 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
878 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
879 | "dev": true,
880 | "requires": {
881 | "has-flag": "^3.0.0"
882 | }
883 | },
884 | "to-regex-range": {
885 | "version": "5.0.1",
886 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
887 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
888 | "dev": true,
889 | "requires": {
890 | "is-number": "^7.0.0"
891 | }
892 | },
893 | "toidentifier": {
894 | "version": "1.0.1",
895 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
896 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
897 | },
898 | "touch": {
899 | "version": "3.1.0",
900 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
901 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
902 | "dev": true,
903 | "requires": {
904 | "nopt": "~1.0.10"
905 | }
906 | },
907 | "type-is": {
908 | "version": "1.6.18",
909 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
910 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
911 | "requires": {
912 | "media-typer": "0.3.0",
913 | "mime-types": "~2.1.24"
914 | }
915 | },
916 | "uid2": {
917 | "version": "0.0.3",
918 | "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz",
919 | "integrity": "sha512-5gSP1liv10Gjp8cMEnFd6shzkL/D6W1uhXSFNCxDC+YI8+L8wkCYCbJ7n77Ezb4wE/xzMogecE+DtamEe9PZjg=="
920 | },
921 | "undefsafe": {
922 | "version": "2.0.5",
923 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
924 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
925 | "dev": true
926 | },
927 | "unpipe": {
928 | "version": "1.0.0",
929 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
930 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
931 | },
932 | "utils-merge": {
933 | "version": "1.0.1",
934 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
935 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
936 | },
937 | "vary": {
938 | "version": "1.1.2",
939 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
940 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
941 | },
942 | "ws": {
943 | "version": "8.2.3",
944 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
945 | "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA=="
946 | },
947 | "yallist": {
948 | "version": "4.0.0",
949 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
950 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
951 | }
952 | }
953 | }
954 |
--------------------------------------------------------------------------------