├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── messages.d.ts
├── package.json
├── public
├── index.html
└── web.js
├── server.ts
├── tsconfig.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = true
9 | tab_width = 2
10 | trim_trailing_whitespace = true
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 michaelneu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Howto WebRTC
2 |
3 | This repository contains the code to my post about WebRTC on dev.to.
4 |
5 | See [server.ts](server.ts) and [public/web.js](public/web.js) for both the server and web implementation.
6 |
7 | ## Usage
8 |
9 | Install all dependencies and start the server:
10 |
11 | ```bash
12 | $ yarn install
13 | $ yarn start
14 | ```
15 |
16 | ## License
17 |
18 | This project is released under the [MIT License](LICENSE).
19 |
--------------------------------------------------------------------------------
/messages.d.ts:
--------------------------------------------------------------------------------
1 | interface LoginWebSocketMessage {
2 | channel: "login";
3 | name: string;
4 | }
5 |
6 | interface StartCallWebSocketMessage {
7 | channel: "start_call";
8 | otherPerson: string;
9 | }
10 |
11 | interface WebRTCIceCandidateWebSocketMessage {
12 | channel: "webrtc_ice_candidate";
13 | candidate: RTCIceCandidate;
14 | otherPerson: string;
15 | }
16 |
17 | interface WebRTCOfferWebSocketMessage {
18 | channel: "webrtc_offer";
19 | offer: RTCSessionDescription;
20 | otherPerson: string;
21 | }
22 |
23 | interface WebRTCAnswerWebSocketMessage {
24 | channel: "webrtc_answer";
25 | answer: RTCSessionDescription;
26 | otherPerson: string;
27 | }
28 |
29 | type WebSocketCallMessage =
30 | StartCallWebSocketMessage
31 | | WebRTCIceCandidateWebSocketMessage
32 | | WebRTCOfferWebSocketMessage
33 | | WebRTCAnswerWebSocketMessage;
34 |
35 | type WebSocketMessage = LoginWebSocketMessage | WebSocketCallMessage;
36 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "howto-webrtc",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "start": "ts-node server.ts"
8 | },
9 | "devDependencies": {
10 | "@types/express": "^4.17.0",
11 | "@types/express-ws": "^3.0.0",
12 | "ts-node": "^8.3.0"
13 | },
14 | "dependencies": {
15 | "express": "^4.17.1",
16 | "express-ws": "^4.0.0",
17 | "tslib": "^1.10.0",
18 | "typescript": "^3.5.3"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
58 |
59 |
60 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/public/web.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | /**
4 | * Hides the given element by setting `display: none`.
5 | * @param {HTMLElement} element The element to hide
6 | */
7 | function hideElement(element) {
8 | element.style.display = "none";
9 | }
10 |
11 | /**
12 | * Shows the given element by resetting the display CSS property.
13 | * @param {HTMLElement} element The element to show
14 | */
15 | function showElement(element) {
16 | element.style.display = "";
17 | }
18 |
19 | const callButton = document.getElementById("call-button");
20 | const videoContainer = document.getElementById("video-container");
21 |
22 | /**
23 | * Hides both local and remote video, but shows the "call" button.
24 | */
25 | function hideVideoCall() {
26 | hideElement(videoContainer);
27 | showElement(callButton);
28 | }
29 |
30 | /**
31 | * Shows both local and remote video, and hides the "call" button.
32 | */
33 | function showVideoCall() {
34 | hideElement(callButton);
35 | showElement(videoContainer);
36 | }
37 |
38 | /** @type {string} */
39 | let otherPerson;
40 |
41 | const username = prompt("What's your name?", `user${Math.floor(Math.random() * 100)}`);
42 | const socketUrl = `ws://${location.host}/ws`;
43 | const socket = new WebSocket(socketUrl);
44 |
45 | /**
46 | * Sends the message over the socket.
47 | * @param {WebSocketMessage} message The message to send
48 | */
49 | function sendMessageToSignallingServer(message) {
50 | const json = JSON.stringify(message);
51 | socket.send(json);
52 | }
53 |
54 | // log in directly after the socket was opened
55 | socket.addEventListener("open", () => {
56 | console.log("websocket connected");
57 | sendMessageToSignallingServer({
58 | channel: "login",
59 | name: username,
60 | });
61 | });
62 |
63 | socket.addEventListener("message", (event) => {
64 | const message = JSON.parse(event.data.toString());
65 | handleMessage(message);
66 | });
67 |
68 | /**
69 | * Processes the incoming message.
70 | * @param {WebSocketMessage} message The incoming message
71 | */
72 | async function handleMessage(message) {
73 | switch (message.channel) {
74 | case "start_call":
75 | console.log(`receiving call from ${message.with}`);
76 | otherPerson = message.otherPerson;
77 | showVideoCall();
78 |
79 | const offer = await webrtc.createOffer();
80 | await webrtc.setLocalDescription(offer);
81 | sendMessageToSignallingServer({
82 | channel: "webrtc_offer",
83 | offer,
84 | otherPerson,
85 | });
86 | break;
87 |
88 | case "webrtc_ice_candidate":
89 | console.log("received ice candidate");
90 | await webrtc.addIceCandidate(message.candidate);
91 | break;
92 |
93 | case "webrtc_offer":
94 | console.log("received webrtc offer");
95 | await webrtc.setRemoteDescription(message.offer);
96 |
97 | const answer = await webrtc.createAnswer();
98 | await webrtc.setLocalDescription(answer);
99 |
100 | sendMessageToSignallingServer({
101 | channel: "webrtc_answer",
102 | answer,
103 | otherPerson,
104 | });
105 | break;
106 |
107 | case "webrtc_answer":
108 | console.log("received webrtc answer");
109 | await webrtc.setRemoteDescription(message.answer);
110 | break;
111 |
112 | default:
113 | console.log("unknown message", message);
114 | break;
115 | }
116 | }
117 |
118 | const webrtc = new RTCPeerConnection({
119 | iceServers: [
120 | {
121 | urls: [
122 | "stun:stun.stunprotocol.org",
123 | ],
124 | },
125 | ],
126 | });
127 |
128 | webrtc.addEventListener("icecandidate", (event) => {
129 | if (!event.candidate) {
130 | return;
131 | }
132 |
133 | sendMessageToSignallingServer({
134 | channel: "webrtc_ice_candidate",
135 | candidate: event.candidate,
136 | otherPerson,
137 | });
138 | });
139 |
140 | webrtc.addEventListener("track", (event) => {
141 | /** @type {HTMLVideoElement} */
142 | const remoteVideo = document.getElementById("remote-video");
143 | remoteVideo.srcObject = event.streams[0];
144 | });
145 |
146 | navigator
147 | .mediaDevices
148 | .getUserMedia({ video: true })
149 | .then((localStream) => {
150 | /** @type {HTMLVideoElement} */
151 | const localVideo = document.getElementById("local-video");
152 | localVideo.srcObject = localStream;
153 |
154 | for (const track of localStream.getTracks()) {
155 | webrtc.addTrack(track, localStream);
156 | }
157 | });
158 |
159 | callButton.addEventListener("click", async () => {
160 | otherPerson = prompt("Who you gonna call?");
161 |
162 | showVideoCall();
163 | sendMessageToSignallingServer({
164 | channel: "start_call",
165 | otherPerson,
166 | });
167 | });
168 |
169 | hideVideoCall();
170 |
--------------------------------------------------------------------------------
/server.ts:
--------------------------------------------------------------------------------
1 | // it's easiest to share typedefs as an ambient declaration file
2 | ///
3 |
4 | import * as express from "express";
5 | import * as expressWs from "express-ws";
6 | import * as WebSocket from "ws";
7 | import { createServer } from "http";
8 |
9 | interface User {
10 | socket: WebSocket;
11 | name: string;
12 | }
13 |
14 | // we'll keep a list of our connected users, as we need to send them messages later
15 | let connectedUsers: User[] = [];
16 |
17 | /**
18 | * Searches the currently connected users and returns the first one connected to the provided socket.
19 | * @param socket The socket to search for
20 | */
21 | function findUserBySocket(socket: WebSocket): User | undefined {
22 | return connectedUsers.find((user) => user.socket === socket);
23 | }
24 |
25 | /**
26 | * Searches the currently connected users and returns the first one with the provided name.
27 | * @param name The name to search for
28 | */
29 | function findUserByName(name: string): User | undefined {
30 | return connectedUsers.find((user) => user.name === name);
31 | }
32 |
33 | /**
34 | * Forwards this message to the person
35 | * @param sender The person originally sending this message
36 | * @param message The received message
37 | */
38 | function forwardMessageToOtherPerson(sender: User, message: WebSocketCallMessage): void {
39 | const receiver = findUserByName(message.otherPerson);
40 | if (!receiver) {
41 | // in case this user doesn't exist, don't do anything
42 | return;
43 | }
44 |
45 | const json = JSON.stringify({
46 | ...message,
47 | otherPerson: sender.name,
48 | });
49 |
50 | receiver.socket.send(json);
51 | }
52 |
53 | /**
54 | * Processes the incoming message.
55 | * @param socket The socket that sent the message
56 | * @param message The message itself
57 | */
58 | function handleMessage(socket: WebSocket, message: WebSocketMessage): void {
59 | const sender = findUserBySocket(socket) || {
60 | name: "[unknown]",
61 | socket,
62 | };
63 |
64 | switch (message.channel) {
65 | case "login":
66 | console.log(`${message.name} joined`);
67 | connectedUsers.push({ socket, name: message.name });
68 | break;
69 |
70 | case "start_call":
71 | console.log(`${sender.name} started a call with ${message.otherPerson}`);
72 | forwardMessageToOtherPerson(sender, message);
73 | break;
74 |
75 | case "webrtc_ice_candidate":
76 | console.log(`received ice candidate from ${sender.name}`);
77 | forwardMessageToOtherPerson(sender, message);
78 | break;
79 |
80 | case "webrtc_offer":
81 | console.log(`received offer from ${sender.name}`);
82 | forwardMessageToOtherPerson(sender, message);
83 | break;
84 |
85 | case "webrtc_answer":
86 | console.log(`received answer from ${sender.name}`);
87 | forwardMessageToOtherPerson(sender, message);
88 | break;
89 |
90 | default:
91 | console.log("unknown message", message);
92 | break;
93 | }
94 | }
95 |
96 | /**
97 | * Adds event listeners to the incoming socket.
98 | * @param socket The incoming WebSocket
99 | */
100 | function handleSocketConnection(socket: WebSocket): void {
101 | socket.addEventListener("message", (event) => {
102 | // incoming messages are strings of buffers. we need to convert them
103 | // to objects first using JSON.parse()
104 | // it's safe to assume we'll only receive valid json here though
105 | const json = JSON.parse(event.data.toString());
106 | handleMessage(socket, json);
107 | });
108 |
109 | socket.addEventListener("close", () => {
110 | // remove the user from our user list
111 | connectedUsers = connectedUsers.filter((user) => {
112 | if (user.socket === socket) {
113 | console.log(`${user.name} disconnected`);
114 | return false;
115 | }
116 |
117 | return true;
118 | });
119 | });
120 | }
121 |
122 | // create an express app, using http `createServer`
123 | const app = express();
124 | const server = createServer(app);
125 |
126 | // we'll serve our public directory under /
127 | app.use("/", express.static("public"));
128 |
129 | // add a websocket listener under /ws
130 | const wsApp = expressWs(app, server).app;
131 | wsApp.ws("/ws", handleSocketConnection);
132 |
133 | // start the server
134 | const port = process.env.PORT || 3000;
135 | server.listen(port, () => {
136 | console.log(`server started on http://localhost:${port}`);
137 | });
138 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "importHelpers": true,
4 | "module": "commonjs",
5 | "noUnusedLocals": true,
6 | "noUnusedParameters": true,
7 | "strict": true,
8 | "target": "es2017"
9 | },
10 | "include": [
11 | "server.ts",
12 | "public/**/*.js"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@types/body-parser@*":
6 | version "1.17.0"
7 | resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c"
8 | integrity sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==
9 | dependencies:
10 | "@types/connect" "*"
11 | "@types/node" "*"
12 |
13 | "@types/connect@*":
14 | version "3.4.32"
15 | resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28"
16 | integrity sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==
17 | dependencies:
18 | "@types/node" "*"
19 |
20 | "@types/events@*":
21 | version "3.0.0"
22 | resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
23 | integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
24 |
25 | "@types/express-serve-static-core@*":
26 | version "4.16.7"
27 | resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.7.tgz#50ba6f8a691c08a3dd9fa7fba25ef3133d298049"
28 | integrity sha512-847KvL8Q1y3TtFLRTXcVakErLJQgdpFSaq+k043xefz9raEf0C7HalpSY7OW5PyjCnY8P7bPW5t/Co9qqp+USg==
29 | dependencies:
30 | "@types/node" "*"
31 | "@types/range-parser" "*"
32 |
33 | "@types/express-ws@^3.0.0":
34 | version "3.0.0"
35 | resolved "https://registry.yarnpkg.com/@types/express-ws/-/express-ws-3.0.0.tgz#89674edba2e9141916fc4d4d30fbd4f810e6b80b"
36 | integrity sha512-GxsWec7Vp6h7sJuK0PwnZHeXNZnOwQn8kHAbCfvii66it5jXHTWzSg5cgHVtESwJfBLOe9SJ5wmM7C6gsDoyQw==
37 | dependencies:
38 | "@types/express" "*"
39 | "@types/express-serve-static-core" "*"
40 | "@types/ws" "*"
41 |
42 | "@types/express@*", "@types/express@^4.17.0":
43 | version "4.17.0"
44 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.0.tgz#49eaedb209582a86f12ed9b725160f12d04ef287"
45 | integrity sha512-CjaMu57cjgjuZbh9DpkloeGxV45CnMGlVd+XpG7Gm9QgVrd7KFq+X4HY0vM+2v0bczS48Wg7bvnMY5TN+Xmcfw==
46 | dependencies:
47 | "@types/body-parser" "*"
48 | "@types/express-serve-static-core" "*"
49 | "@types/serve-static" "*"
50 |
51 | "@types/mime@*":
52 | version "2.0.1"
53 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
54 | integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==
55 |
56 | "@types/node@*":
57 | version "12.6.2"
58 | resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.2.tgz#a5ccec6abb6060d5f20d256fb03ed743e9774999"
59 | integrity sha512-gojym4tX0FWeV2gsW4Xmzo5wxGjXGm550oVUII7f7G5o4BV6c7DBdiG1RRQd+y1bvqRyYtPfMK85UM95vsapqQ==
60 |
61 | "@types/range-parser@*":
62 | version "1.2.3"
63 | resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
64 | integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
65 |
66 | "@types/serve-static@*":
67 | version "1.13.2"
68 | resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48"
69 | integrity sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==
70 | dependencies:
71 | "@types/express-serve-static-core" "*"
72 | "@types/mime" "*"
73 |
74 | "@types/ws@*":
75 | version "6.0.1"
76 | resolved "https://registry.yarnpkg.com/@types/ws/-/ws-6.0.1.tgz#ca7a3f3756aa12f62a0a62145ed14c6db25d5a28"
77 | integrity sha512-EzH8k1gyZ4xih/MaZTXwT2xOkPiIMSrhQ9b8wrlX88L0T02eYsddatQlwVFlEPyEqV0ChpdpNnE51QPH6NVT4Q==
78 | dependencies:
79 | "@types/events" "*"
80 | "@types/node" "*"
81 |
82 | accepts@~1.3.7:
83 | version "1.3.7"
84 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
85 | integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
86 | dependencies:
87 | mime-types "~2.1.24"
88 | negotiator "0.6.2"
89 |
90 | arg@^4.1.0:
91 | version "4.1.0"
92 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0"
93 | integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==
94 |
95 | array-flatten@1.1.1:
96 | version "1.1.1"
97 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
98 | integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
99 |
100 | async-limiter@~1.0.0:
101 | version "1.0.0"
102 | resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
103 | integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
104 |
105 | body-parser@1.19.0:
106 | version "1.19.0"
107 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
108 | integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
109 | dependencies:
110 | bytes "3.1.0"
111 | content-type "~1.0.4"
112 | debug "2.6.9"
113 | depd "~1.1.2"
114 | http-errors "1.7.2"
115 | iconv-lite "0.4.24"
116 | on-finished "~2.3.0"
117 | qs "6.7.0"
118 | raw-body "2.4.0"
119 | type-is "~1.6.17"
120 |
121 | buffer-from@^1.0.0:
122 | version "1.1.1"
123 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
124 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
125 |
126 | bytes@3.1.0:
127 | version "3.1.0"
128 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
129 | integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
130 |
131 | content-disposition@0.5.3:
132 | version "0.5.3"
133 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
134 | integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
135 | dependencies:
136 | safe-buffer "5.1.2"
137 |
138 | content-type@~1.0.4:
139 | version "1.0.4"
140 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
141 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
142 |
143 | cookie-signature@1.0.6:
144 | version "1.0.6"
145 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
146 | integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
147 |
148 | cookie@0.4.0:
149 | version "0.4.0"
150 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
151 | integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
152 |
153 | debug@2.6.9:
154 | version "2.6.9"
155 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
156 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
157 | dependencies:
158 | ms "2.0.0"
159 |
160 | depd@~1.1.2:
161 | version "1.1.2"
162 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
163 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
164 |
165 | destroy@~1.0.4:
166 | version "1.0.4"
167 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
168 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
169 |
170 | diff@^4.0.1:
171 | version "4.0.1"
172 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff"
173 | integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==
174 |
175 | ee-first@1.1.1:
176 | version "1.1.1"
177 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
178 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
179 |
180 | encodeurl@~1.0.2:
181 | version "1.0.2"
182 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
183 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
184 |
185 | escape-html@~1.0.3:
186 | version "1.0.3"
187 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
188 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
189 |
190 | etag@~1.8.1:
191 | version "1.8.1"
192 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
193 | integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
194 |
195 | express-ws@^4.0.0:
196 | version "4.0.0"
197 | resolved "https://registry.yarnpkg.com/express-ws/-/express-ws-4.0.0.tgz#dabd8dc974516418902a41fe6e30ed949b4d36c4"
198 | integrity sha512-KEyUw8AwRET2iFjFsI1EJQrJ/fHeGiJtgpYgEWG3yDv4l/To/m3a2GaYfeGyB3lsWdvbesjF5XCMx+SVBgAAYw==
199 | dependencies:
200 | ws "^5.2.0"
201 |
202 | express@^4.17.1:
203 | version "4.17.1"
204 | resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
205 | integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
206 | dependencies:
207 | accepts "~1.3.7"
208 | array-flatten "1.1.1"
209 | body-parser "1.19.0"
210 | content-disposition "0.5.3"
211 | content-type "~1.0.4"
212 | cookie "0.4.0"
213 | cookie-signature "1.0.6"
214 | debug "2.6.9"
215 | depd "~1.1.2"
216 | encodeurl "~1.0.2"
217 | escape-html "~1.0.3"
218 | etag "~1.8.1"
219 | finalhandler "~1.1.2"
220 | fresh "0.5.2"
221 | merge-descriptors "1.0.1"
222 | methods "~1.1.2"
223 | on-finished "~2.3.0"
224 | parseurl "~1.3.3"
225 | path-to-regexp "0.1.7"
226 | proxy-addr "~2.0.5"
227 | qs "6.7.0"
228 | range-parser "~1.2.1"
229 | safe-buffer "5.1.2"
230 | send "0.17.1"
231 | serve-static "1.14.1"
232 | setprototypeof "1.1.1"
233 | statuses "~1.5.0"
234 | type-is "~1.6.18"
235 | utils-merge "1.0.1"
236 | vary "~1.1.2"
237 |
238 | finalhandler@~1.1.2:
239 | version "1.1.2"
240 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
241 | integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
242 | dependencies:
243 | debug "2.6.9"
244 | encodeurl "~1.0.2"
245 | escape-html "~1.0.3"
246 | on-finished "~2.3.0"
247 | parseurl "~1.3.3"
248 | statuses "~1.5.0"
249 | unpipe "~1.0.0"
250 |
251 | forwarded@~0.1.2:
252 | version "0.1.2"
253 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
254 | integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
255 |
256 | fresh@0.5.2:
257 | version "0.5.2"
258 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
259 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
260 |
261 | http-errors@1.7.2:
262 | version "1.7.2"
263 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
264 | integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
265 | dependencies:
266 | depd "~1.1.2"
267 | inherits "2.0.3"
268 | setprototypeof "1.1.1"
269 | statuses ">= 1.5.0 < 2"
270 | toidentifier "1.0.0"
271 |
272 | http-errors@~1.7.2:
273 | version "1.7.3"
274 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
275 | integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
276 | dependencies:
277 | depd "~1.1.2"
278 | inherits "2.0.4"
279 | setprototypeof "1.1.1"
280 | statuses ">= 1.5.0 < 2"
281 | toidentifier "1.0.0"
282 |
283 | iconv-lite@0.4.24:
284 | version "0.4.24"
285 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
286 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
287 | dependencies:
288 | safer-buffer ">= 2.1.2 < 3"
289 |
290 | inherits@2.0.3:
291 | version "2.0.3"
292 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
293 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
294 |
295 | inherits@2.0.4:
296 | version "2.0.4"
297 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
298 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
299 |
300 | ipaddr.js@1.9.0:
301 | version "1.9.0"
302 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65"
303 | integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==
304 |
305 | make-error@^1.1.1:
306 | version "1.3.5"
307 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
308 | integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
309 |
310 | media-typer@0.3.0:
311 | version "0.3.0"
312 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
313 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
314 |
315 | merge-descriptors@1.0.1:
316 | version "1.0.1"
317 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
318 | integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
319 |
320 | methods@~1.1.2:
321 | version "1.1.2"
322 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
323 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
324 |
325 | mime-db@1.40.0:
326 | version "1.40.0"
327 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
328 | integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==
329 |
330 | mime-types@~2.1.24:
331 | version "2.1.24"
332 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81"
333 | integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==
334 | dependencies:
335 | mime-db "1.40.0"
336 |
337 | mime@1.6.0:
338 | version "1.6.0"
339 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
340 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
341 |
342 | ms@2.0.0:
343 | version "2.0.0"
344 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
345 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
346 |
347 | ms@2.1.1:
348 | version "2.1.1"
349 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
350 | integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
351 |
352 | negotiator@0.6.2:
353 | version "0.6.2"
354 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
355 | integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
356 |
357 | on-finished@~2.3.0:
358 | version "2.3.0"
359 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
360 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
361 | dependencies:
362 | ee-first "1.1.1"
363 |
364 | parseurl@~1.3.3:
365 | version "1.3.3"
366 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
367 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
368 |
369 | path-to-regexp@0.1.7:
370 | version "0.1.7"
371 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
372 | integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
373 |
374 | proxy-addr@~2.0.5:
375 | version "2.0.5"
376 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
377 | integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==
378 | dependencies:
379 | forwarded "~0.1.2"
380 | ipaddr.js "1.9.0"
381 |
382 | qs@6.7.0:
383 | version "6.7.0"
384 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
385 | integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
386 |
387 | range-parser@~1.2.1:
388 | version "1.2.1"
389 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
390 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
391 |
392 | raw-body@2.4.0:
393 | version "2.4.0"
394 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
395 | integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
396 | dependencies:
397 | bytes "3.1.0"
398 | http-errors "1.7.2"
399 | iconv-lite "0.4.24"
400 | unpipe "1.0.0"
401 |
402 | safe-buffer@5.1.2:
403 | version "5.1.2"
404 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
405 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
406 |
407 | "safer-buffer@>= 2.1.2 < 3":
408 | version "2.1.2"
409 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
410 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
411 |
412 | send@0.17.1:
413 | version "0.17.1"
414 | resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
415 | integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
416 | dependencies:
417 | debug "2.6.9"
418 | depd "~1.1.2"
419 | destroy "~1.0.4"
420 | encodeurl "~1.0.2"
421 | escape-html "~1.0.3"
422 | etag "~1.8.1"
423 | fresh "0.5.2"
424 | http-errors "~1.7.2"
425 | mime "1.6.0"
426 | ms "2.1.1"
427 | on-finished "~2.3.0"
428 | range-parser "~1.2.1"
429 | statuses "~1.5.0"
430 |
431 | serve-static@1.14.1:
432 | version "1.14.1"
433 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
434 | integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
435 | dependencies:
436 | encodeurl "~1.0.2"
437 | escape-html "~1.0.3"
438 | parseurl "~1.3.3"
439 | send "0.17.1"
440 |
441 | setprototypeof@1.1.1:
442 | version "1.1.1"
443 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
444 | integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
445 |
446 | source-map-support@^0.5.6:
447 | version "0.5.12"
448 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
449 | integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
450 | dependencies:
451 | buffer-from "^1.0.0"
452 | source-map "^0.6.0"
453 |
454 | source-map@^0.6.0:
455 | version "0.6.1"
456 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
457 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
458 |
459 | "statuses@>= 1.5.0 < 2", statuses@~1.5.0:
460 | version "1.5.0"
461 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
462 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
463 |
464 | toidentifier@1.0.0:
465 | version "1.0.0"
466 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
467 | integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
468 |
469 | ts-node@^8.3.0:
470 | version "8.3.0"
471 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.3.0.tgz#e4059618411371924a1fb5f3b125915f324efb57"
472 | integrity sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ==
473 | dependencies:
474 | arg "^4.1.0"
475 | diff "^4.0.1"
476 | make-error "^1.1.1"
477 | source-map-support "^0.5.6"
478 | yn "^3.0.0"
479 |
480 | tslib@^1.10.0:
481 | version "1.10.0"
482 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
483 | integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
484 |
485 | type-is@~1.6.17, type-is@~1.6.18:
486 | version "1.6.18"
487 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
488 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
489 | dependencies:
490 | media-typer "0.3.0"
491 | mime-types "~2.1.24"
492 |
493 | typescript@^3.5.3:
494 | version "3.5.3"
495 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
496 | integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
497 |
498 | unpipe@1.0.0, unpipe@~1.0.0:
499 | version "1.0.0"
500 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
501 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
502 |
503 | utils-merge@1.0.1:
504 | version "1.0.1"
505 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
506 | integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
507 |
508 | vary@~1.1.2:
509 | version "1.1.2"
510 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
511 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
512 |
513 | ws@^5.2.0:
514 | version "5.2.2"
515 | resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
516 | integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
517 | dependencies:
518 | async-limiter "~1.0.0"
519 |
520 | yn@^3.0.0:
521 | version "3.1.0"
522 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.0.tgz#fcbe2db63610361afcc5eb9e0ac91e976d046114"
523 | integrity sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg==
524 |
--------------------------------------------------------------------------------