├── .gitignore
├── server
├── .gitignore
├── Procfile
├── router.js
├── package.json
├── users.js
├── index.js
└── package-lock.json
├── .github
└── FUNDING.yml
├── .netlify
└── state.json
├── client
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── components
│ │ ├── Messages
│ │ │ ├── Messages.css
│ │ │ ├── Messages.js
│ │ │ └── Message
│ │ │ │ ├── Message.js
│ │ │ │ └── Message.css
│ │ ├── Input
│ │ │ ├── Input.css
│ │ │ └── Input.js
│ │ ├── InfoBar
│ │ │ ├── InfoBar.css
│ │ │ └── InfoBar.js
│ │ ├── TextContainer
│ │ │ ├── TextContainer.css
│ │ │ └── TextContainer.js
│ │ ├── Chat
│ │ │ ├── Chat.css
│ │ │ └── Chat.js
│ │ └── Join
│ │ │ ├── Join.js
│ │ │ └── Join.css
│ ├── icons
│ │ ├── closeIcon.png
│ │ └── onlineIcon.png
│ ├── index.js
│ └── App.js
├── .gitignore
├── package.json
├── .eslintrc.js
└── README.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /netlify
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
--------------------------------------------------------------------------------
/server/Procfile:
--------------------------------------------------------------------------------
1 | web: node index.js
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: adrianhajdin
2 |
--------------------------------------------------------------------------------
/.netlify/state.json:
--------------------------------------------------------------------------------
1 | {
2 | "siteId": "70e96aae-6490-4d7b-b117-50aa0efd24fc"
3 | }
--------------------------------------------------------------------------------
/client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appledesire/react-chat-application/HEAD/client/public/favicon.ico
--------------------------------------------------------------------------------
/client/src/components/Messages/Messages.css:
--------------------------------------------------------------------------------
1 | .messages {
2 | padding: 5% 0;
3 | overflow: auto;
4 | flex: auto;
5 | }
--------------------------------------------------------------------------------
/client/src/icons/closeIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appledesire/react-chat-application/HEAD/client/src/icons/closeIcon.png
--------------------------------------------------------------------------------
/client/src/icons/onlineIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appledesire/react-chat-application/HEAD/client/src/icons/onlineIcon.png
--------------------------------------------------------------------------------
/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import App from './App';
5 |
6 | ReactDOM.render(, document.getElementById('root'));
--------------------------------------------------------------------------------
/server/router.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const router = express.Router();
3 |
4 | router.get("/", (req, res) => {
5 | res.send({ response: "Server is up and running." }).status(200);
6 | });
7 |
8 | module.exports = router;
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | # dependencies
2 | /node_modules
3 | /.pnp
4 | .pnp.js
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "nodemon index.js"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "cors": "^2.8.5",
14 | "express": "^4.17.1",
15 | "socket.io": "^2.2.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/client/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Chat from './components/Chat/Chat';
4 | import Join from './components/Join/Join';
5 |
6 | import { BrowserRouter as Router, Route } from "react-router-dom";
7 |
8 | const App = () => {
9 | return (
10 |
11 |
12 |
13 |
14 | );
15 | }
16 |
17 | export default App;
18 |
--------------------------------------------------------------------------------
/client/src/components/Messages/Messages.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import ScrollToBottom from 'react-scroll-to-bottom';
4 |
5 | import Message from './Message/Message';
6 |
7 | import './Messages.css';
8 |
9 | const Messages = ({ messages, name }) => (
10 |
11 | {messages.map((message, i) =>
)}
12 |
13 | );
14 |
15 | export default Messages;
--------------------------------------------------------------------------------
/client/src/components/Input/Input.css:
--------------------------------------------------------------------------------
1 | .form {
2 | display: flex;
3 | border-top: 2px solid #D3D3D3;
4 | }
5 |
6 | .input {
7 | border: none;
8 | border-radius: 0;
9 | padding: 5%;
10 | width: 80%;
11 | font-size: 1.2em;
12 | }
13 |
14 | input:focus, textarea:focus, select:focus{
15 | outline: none;
16 | }
17 |
18 | .sendButton {
19 | color: #fff !important;
20 | text-transform: uppercase;
21 | text-decoration: none;
22 | background: #2979FF;
23 | padding: 20px;
24 | display: inline-block;
25 | border: none;
26 | width: 20%;
27 | }
--------------------------------------------------------------------------------
/client/src/components/InfoBar/InfoBar.css:
--------------------------------------------------------------------------------
1 | .infoBar {
2 | display: flex;
3 | align-items: center;
4 | justify-content: space-between;
5 | background: #2979FF;
6 | border-radius: 4px 4px 0 0;
7 | height: 60px;
8 | width: 100%;
9 | }
10 |
11 | .leftInnerContainer {
12 | flex: 0.5;
13 | display: flex;
14 | align-items: center;
15 | margin-left: 5%;
16 | color: white;
17 | }
18 |
19 | .rightInnerContainer {
20 | display: flex;
21 | flex: 0.5;
22 | justify-content: flex-end;
23 | margin-right: 5%;
24 | }
25 |
26 | .onlineIcon {
27 | margin-right: 5%;
28 | }
29 |
--------------------------------------------------------------------------------
/client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | React App
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/client/src/components/Input/Input.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import './Input.css';
4 |
5 | const Input = ({ setMessage, sendMessage, message }) => (
6 |
17 | )
18 |
19 | export default Input;
--------------------------------------------------------------------------------
/client/src/components/InfoBar/InfoBar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import onlineIcon from '../../icons/onlineIcon.png';
4 | import closeIcon from '../../icons/closeIcon.png';
5 |
6 | import './InfoBar.css';
7 |
8 | const InfoBar = ({ room }) => (
9 |
10 |
11 |

12 |
{room}
13 |
14 |
15 |

16 |
17 |
18 | );
19 |
20 | export default InfoBar;
--------------------------------------------------------------------------------
/client/src/components/TextContainer/TextContainer.css:
--------------------------------------------------------------------------------
1 | .textContainer {
2 | display: flex;
3 | flex-direction: column;
4 | margin-left: 100px;
5 | color: white;
6 | height: 60%;
7 | justify-content: space-between;
8 | }
9 |
10 | .activeContainer {
11 | display: flex;
12 | align-items: center;
13 | margin-bottom: 50%;
14 | }
15 |
16 | .activeItem {
17 | display: flex;
18 | align-items: center;
19 | }
20 |
21 | .activeContainer img {
22 | padding-left: 10px;
23 | }
24 |
25 | .textContainer h1 {
26 | margin-bottom: 0px;
27 | }
28 |
29 | @media (min-width: 320px) and (max-width: 1200px) {
30 | .textContainer {
31 | display: none;
32 | }
33 | }
--------------------------------------------------------------------------------
/client/src/components/Chat/Chat.css:
--------------------------------------------------------------------------------
1 | .outerContainer {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | height: 100vh;
6 | background-color: #1A1A1D;
7 | }
8 |
9 | .container {
10 | display: flex;
11 | flex-direction: column;
12 | justify-content: space-between;
13 | background: #FFFFFF;
14 | border-radius: 8px;
15 | height: 60%;
16 | width: 35%;
17 | }
18 |
19 | @media (min-width: 320px) and (max-width: 480px) {
20 | .outerContainer {
21 | height: 100%;
22 | }
23 |
24 | .container {
25 | width: 100%;
26 | height: 100%;
27 | }
28 | }
29 |
30 | @media (min-width: 480px) and (max-width: 1200px) {
31 | .container {
32 | width: 60%;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Realtime Chat Application
2 |
3 | ### [Live Site](https://realtime-chat-application.netlify.com)
4 |
5 | 
6 |
7 | ## Introduction
8 | This is a code repository for the corresponding video tutorial.
9 |
10 | In this video, we will create a full Realtime Chat Application. We're going to use React on the front end, with NodeJS + Socket.io web socket library on the back end.
11 |
12 | By the end of this video, you will have a strong understanding of how to send and receive messages using web sockets and Socket.io to make any real-time application.
13 |
14 | ## Launch your development career with project-based coaching - https://www.jsmastery.pro
15 |
16 | Setup:
17 | - run ```npm i && npm start``` for both client and server side to start the development server
18 |
--------------------------------------------------------------------------------
/server/users.js:
--------------------------------------------------------------------------------
1 | const users = [];
2 |
3 | const addUser = ({ id, name, room }) => {
4 | name = name.trim().toLowerCase();
5 | room = room.trim().toLowerCase();
6 |
7 | const existingUser = users.find((user) => user.room === room && user.name === name);
8 |
9 | if(!name || !room) return { error: 'Username and room are required.' };
10 | if(existingUser) return { error: 'Username is taken.' };
11 |
12 | const user = { id, name, room };
13 |
14 | users.push(user);
15 |
16 | return { user };
17 | }
18 |
19 | const removeUser = (id) => {
20 | const index = users.findIndex((user) => user.id === id);
21 |
22 | if(index !== -1) return users.splice(index, 1)[0];
23 | }
24 |
25 | const getUser = (id) => users.find((user) => user.id === id);
26 |
27 | const getUsersInRoom = (room) => users.filter((user) => user.room === room);
28 |
29 | module.exports = { addUser, removeUser, getUser, getUsersInRoom };
--------------------------------------------------------------------------------
/client/src/components/Join/Join.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Link } from "react-router-dom";
3 |
4 | import './Join.css';
5 |
6 | export default function SignIn() {
7 | const [name, setName] = useState('');
8 | const [room, setRoom] = useState('');
9 |
10 | return (
11 |
12 |
13 |
Join
14 |
15 | setName(event.target.value)} />
16 |
17 |
18 | setRoom(event.target.value)} />
19 |
20 |
(!name || !room) ? e.preventDefault() : null} to={`/chat?name=${name}&room=${room}`}>
21 |
22 |
23 |
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/client/src/components/Messages/Message/Message.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import './Message.css';
4 |
5 | import ReactEmoji from 'react-emoji';
6 |
7 | const Message = ({ message: { text, user }, name }) => {
8 | let isSentByCurrentUser = false;
9 |
10 | const trimmedName = name.trim().toLowerCase();
11 |
12 | if(user === trimmedName) {
13 | isSentByCurrentUser = true;
14 | }
15 |
16 | return (
17 | isSentByCurrentUser
18 | ? (
19 |
20 |
{trimmedName}
21 |
22 |
{ReactEmoji.emojify(text)}
23 |
24 |
25 | )
26 | : (
27 |
28 |
29 |
{ReactEmoji.emojify(text)}
30 |
31 |
{user}
32 |
33 | )
34 | );
35 | }
36 |
37 | export default Message;
--------------------------------------------------------------------------------
/client/src/components/TextContainer/TextContainer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import onlineIcon from '../../icons/onlineIcon.png';
4 |
5 | import './TextContainer.css';
6 |
7 | const TextContainer = ({ users }) => (
8 |
9 |
10 |
Realtime Chat Application 💬
11 | Created with React, Express, Node and Socket.IO ❤️
12 | Try it out right now! ⬅️
13 |
14 | {
15 | users
16 | ? (
17 |
18 |
People currently chatting:
19 |
20 |
21 | {users.map(({name}) => (
22 |
23 | {name}
24 |

25 |
26 | ))}
27 |
28 |
29 |
30 | )
31 | : null
32 | }
33 |
34 | );
35 |
36 | export default TextContainer;
--------------------------------------------------------------------------------
/client/src/components/Messages/Message/Message.css:
--------------------------------------------------------------------------------
1 | .messageBox {
2 | background: #F3F3F3;
3 | border-radius: 20px;
4 | padding: 5px 20px;
5 | color: white;
6 | display: inline-block;
7 | max-width: 80%;
8 | }
9 |
10 | .messageText {
11 | width: 100%;
12 | letter-spacing: 0;
13 | float: left;
14 | font-size: 1.1em;
15 | word-wrap: break-word;
16 | }
17 |
18 | .messageText img {
19 | vertical-align: middle;
20 | }
21 |
22 | .messageContainer {
23 | display: flex;
24 | justify-content: flex-end;
25 | padding: 0 5%;
26 | margin-top: 3px;
27 | }
28 |
29 | .sentText {
30 | display: flex;
31 | align-items: center;
32 | font-family: Helvetica;
33 | color: #828282;
34 | letter-spacing: 0.3px;
35 | }
36 |
37 | .pl-10 {
38 | padding-left: 10px;
39 | }
40 |
41 | .pr-10 {
42 | padding-right: 10px;
43 | }
44 |
45 | .justifyStart {
46 | justify-content: flex-start;
47 | }
48 |
49 | .justifyEnd {
50 | justify-content: flex-end;
51 | }
52 |
53 | .colorWhite {
54 | color: white;
55 | }
56 |
57 | .colorDark {
58 | color: #353535;
59 | }
60 |
61 | .backgroundBlue {
62 | background: #2979FF;
63 | }
64 |
65 | .backgroundLight {
66 | background: #F3F3F3;
67 | }
68 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "project_chat_application",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "query-string": "^6.8.2",
7 | "react": "^16.9.0",
8 | "react-dom": "^16.9.0",
9 | "react-emoji": "^0.5.0",
10 | "react-router-dom": "^5.0.1",
11 | "react-scripts": "3.1.1",
12 | "react-scroll-to-bottom": "^1.3.2",
13 | "socket.io-client": "^2.2.0"
14 | },
15 | "scripts": {
16 | "start": "react-scripts start",
17 | "build": "react-scripts build",
18 | "test": "react-scripts test",
19 | "eject": "react-scripts eject"
20 | },
21 | "eslintConfig": {
22 | "extends": "react-app"
23 | },
24 | "browserslist": {
25 | "production": [
26 | ">0.2%",
27 | "not dead",
28 | "not op_mini all"
29 | ],
30 | "development": [
31 | "last 1 chrome version",
32 | "last 1 firefox version",
33 | "last 1 safari version"
34 | ]
35 | },
36 | "devDependencies": {
37 | "eslint": "^6.2.2",
38 | "eslint-config-airbnb": "^18.0.1",
39 | "eslint-plugin-import": "^2.18.2",
40 | "eslint-plugin-jsx-a11y": "^6.2.3",
41 | "eslint-plugin-react": "^7.14.3",
42 | "eslint-plugin-react-hooks": "^1.7.0"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/client/src/components/Join/Join.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | font-family: 'Roboto', sans-serif;
3 | padding: 0;
4 | margin: 0;
5 | }
6 |
7 | #root {
8 | height: 100vh;
9 | }
10 |
11 | * {
12 | box-sizing: border-box;
13 | }
14 |
15 | .joinOuterContainer {
16 | display: flex;
17 | justify-content: center;
18 | text-align: center;
19 | height: 100vh;
20 | align-items: center;
21 | background-color: #1A1A1D;
22 | }
23 |
24 | .joinInnerContainer {
25 | width: 20%;
26 | }
27 |
28 | .joinInput {
29 | border-radius: 0;
30 | padding: 15px 20px;
31 | width: 100%;
32 | }
33 |
34 | .heading {
35 | color: white;
36 | font-size: 2.5em;
37 | padding-bottom: 10px;
38 | border-bottom: 2px solid white;
39 | }
40 |
41 | .button {
42 | color: #fff !important;
43 | text-transform: uppercase;
44 | text-decoration: none;
45 | background: #2979FF;
46 | padding: 20px;
47 | border-radius: 5px;
48 | display: inline-block;
49 | border: none;
50 | width: 100%;
51 | }
52 |
53 | .mt-20 {
54 | margin-top: 20px;
55 | }
56 |
57 | @media (min-width: 320px) and (max-width: 480px) {
58 | .joinOuterContainer {
59 | height: 100%;
60 | }
61 |
62 | .joinInnerContainer {
63 | width: 90%;
64 | }
65 |
66 |
67 | }
68 |
69 | button:focus {
70 | outline: 0;
71 | }
--------------------------------------------------------------------------------
/client/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "extends": "airbnb",
3 | "parser": "babel-eslint",
4 | "env": {
5 | "browser": true,
6 | "node": true,
7 | "mocha": true
8 | },
9 | "rules": {
10 | "import/prefer-default-export": 0,
11 | "max-len": [
12 | 2,
13 | 250
14 | ],
15 | "no-multiple-empty-lines": [
16 | "error",
17 | {
18 | "max": 1,
19 | "maxEOF": 1
20 | }
21 | ],
22 | "no-underscore-dangle": [
23 | "error",
24 | {
25 | "allow": [
26 | "_d",
27 | "_dh",
28 | "_h",
29 | "_id",
30 | "_m",
31 | "_n",
32 | "_t",
33 | "_text"
34 | ]
35 | }
36 | ],
37 | "object-curly-newline": 0,
38 | "react/jsx-filename-extension": 0,
39 | "react/jsx-one-expression-per-line": 0,
40 | "jsx-a11y/click-events-have-key-events": 0,
41 | "jsx-a11y/alt-text": 0,
42 | "jsx-a11y/no-autofocus": 0,
43 | "jsx-a11y/no-static-element-interactions": 0,
44 | "react/no-array-index-key": 0,
45 | "jsx-a11y/anchor-is-valid": [
46 | "error",
47 | {
48 | "components": [
49 | "Link"
50 | ],
51 | "specialLink": [
52 | "to",
53 | "hrefLeft",
54 | "hrefRight"
55 | ],
56 | "aspects": [
57 | "noHref",
58 | "invalidHref",
59 | "preferButton"
60 | ]
61 | }
62 | ]
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const express = require('express');
3 | const socketio = require('socket.io');
4 | const cors = require('cors');
5 |
6 | const { addUser, removeUser, getUser, getUsersInRoom } = require('./users');
7 |
8 | const router = require('./router');
9 |
10 | const app = express();
11 | const server = http.createServer(app);
12 | const io = socketio(server);
13 |
14 | app.use(cors());
15 | app.use(router);
16 |
17 | io.on('connect', (socket) => {
18 | socket.on('join', ({ name, room }, callback) => {
19 | const { error, user } = addUser({ id: socket.id, name, room });
20 |
21 | if(error) return callback(error);
22 |
23 | socket.join(user.room);
24 |
25 | socket.emit('message', { user: 'admin', text: `${user.name}, welcome to room ${user.room}.`});
26 | socket.broadcast.to(user.room).emit('message', { user: 'admin', text: `${user.name} has joined!` });
27 |
28 | io.to(user.room).emit('roomData', { room: user.room, users: getUsersInRoom(user.room) });
29 |
30 | callback();
31 | });
32 |
33 | socket.on('sendMessage', (message, callback) => {
34 | const user = getUser(socket.id);
35 |
36 | io.to(user.room).emit('message', { user: user.name, text: message });
37 |
38 | callback();
39 | });
40 |
41 | socket.on('disconnect', () => {
42 | const user = removeUser(socket.id);
43 |
44 | if(user) {
45 | io.to(user.room).emit('message', { user: 'Admin', text: `${user.name} has left.` });
46 | io.to(user.room).emit('roomData', { room: user.room, users: getUsersInRoom(user.room)});
47 | }
48 | })
49 | });
50 |
51 | server.listen(process.env.PORT || 5000, () => console.log(`Server has started.`));
--------------------------------------------------------------------------------
/client/src/components/Chat/Chat.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import queryString from 'query-string';
3 | import io from "socket.io-client";
4 |
5 | import TextContainer from '../TextContainer/TextContainer';
6 | import Messages from '../Messages/Messages';
7 | import InfoBar from '../InfoBar/InfoBar';
8 | import Input from '../Input/Input';
9 |
10 | import './Chat.css';
11 |
12 | const ENDPOINT = 'https://project-chat-application.herokuapp.com/';
13 |
14 | let socket;
15 |
16 | const Chat = ({ location }) => {
17 | const [name, setName] = useState('');
18 | const [room, setRoom] = useState('');
19 | const [users, setUsers] = useState('');
20 | const [message, setMessage] = useState('');
21 | const [messages, setMessages] = useState([]);
22 |
23 | useEffect(() => {
24 | const { name, room } = queryString.parse(location.search);
25 |
26 | socket = io(ENDPOINT);
27 |
28 | setRoom(room);
29 | setName(name)
30 |
31 | socket.emit('join', { name, room }, (error) => {
32 | if(error) {
33 | alert(error);
34 | }
35 | });
36 | }, [ENDPOINT, location.search]);
37 |
38 | useEffect(() => {
39 | socket.on('message', message => {
40 | setMessages(messages => [ ...messages, message ]);
41 | });
42 |
43 | socket.on("roomData", ({ users }) => {
44 | setUsers(users);
45 | });
46 | }, []);
47 |
48 | const sendMessage = (event) => {
49 | event.preventDefault();
50 |
51 | if(message) {
52 | socket.emit('sendMessage', message, () => setMessage(''));
53 | }
54 | }
55 |
56 | return (
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | );
66 | }
67 |
68 | export default Chat;
69 |
--------------------------------------------------------------------------------
/client/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `npm start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `npm test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `npm run build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
29 |
30 | ### `npm run eject`
31 |
32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
33 |
34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
35 |
36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
37 |
38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
39 |
40 | ## Learn More
41 |
42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
43 |
44 | To learn React, check out the [React documentation](https://reactjs.org/).
45 |
46 | ### Code Splitting
47 |
48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
49 |
50 | ### Analyzing the Bundle Size
51 |
52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
53 |
54 | ### Making a Progressive Web App
55 |
56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
57 |
58 | ### Advanced Configuration
59 |
60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
61 |
62 | ### Deployment
63 |
64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
65 |
66 | ### `npm run build` fails to minify
67 |
68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
69 |
--------------------------------------------------------------------------------
/server/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "accepts": {
8 | "version": "1.3.7",
9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
11 | "requires": {
12 | "mime-types": "~2.1.24",
13 | "negotiator": "0.6.2"
14 | }
15 | },
16 | "after": {
17 | "version": "0.8.2",
18 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
19 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
20 | },
21 | "array-flatten": {
22 | "version": "1.1.1",
23 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
24 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
25 | },
26 | "arraybuffer.slice": {
27 | "version": "0.0.7",
28 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
29 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
30 | },
31 | "async-limiter": {
32 | "version": "1.0.1",
33 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
34 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
35 | },
36 | "backo2": {
37 | "version": "1.0.2",
38 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
39 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
40 | },
41 | "base64-arraybuffer": {
42 | "version": "0.1.5",
43 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
44 | "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
45 | },
46 | "base64id": {
47 | "version": "1.0.0",
48 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
49 | "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY="
50 | },
51 | "better-assert": {
52 | "version": "1.0.2",
53 | "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
54 | "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
55 | "requires": {
56 | "callsite": "1.0.0"
57 | }
58 | },
59 | "blob": {
60 | "version": "0.0.5",
61 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
62 | "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
63 | },
64 | "body-parser": {
65 | "version": "1.19.0",
66 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
67 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
68 | "requires": {
69 | "bytes": "3.1.0",
70 | "content-type": "~1.0.4",
71 | "debug": "2.6.9",
72 | "depd": "~1.1.2",
73 | "http-errors": "1.7.2",
74 | "iconv-lite": "0.4.24",
75 | "on-finished": "~2.3.0",
76 | "qs": "6.7.0",
77 | "raw-body": "2.4.0",
78 | "type-is": "~1.6.17"
79 | }
80 | },
81 | "bytes": {
82 | "version": "3.1.0",
83 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
84 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
85 | },
86 | "callsite": {
87 | "version": "1.0.0",
88 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
89 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA="
90 | },
91 | "component-bind": {
92 | "version": "1.0.0",
93 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
94 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
95 | },
96 | "component-emitter": {
97 | "version": "1.2.1",
98 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
99 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
100 | },
101 | "component-inherit": {
102 | "version": "0.0.3",
103 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
104 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
105 | },
106 | "content-disposition": {
107 | "version": "0.5.3",
108 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
109 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
110 | "requires": {
111 | "safe-buffer": "5.1.2"
112 | }
113 | },
114 | "content-type": {
115 | "version": "1.0.4",
116 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
117 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
118 | },
119 | "cookie": {
120 | "version": "0.4.0",
121 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
122 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
123 | },
124 | "cookie-signature": {
125 | "version": "1.0.6",
126 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
127 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
128 | },
129 | "cors": {
130 | "version": "2.8.5",
131 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
132 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
133 | "requires": {
134 | "object-assign": "^4",
135 | "vary": "^1"
136 | }
137 | },
138 | "debug": {
139 | "version": "2.6.9",
140 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
141 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
142 | "requires": {
143 | "ms": "2.0.0"
144 | }
145 | },
146 | "depd": {
147 | "version": "1.1.2",
148 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
149 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
150 | },
151 | "destroy": {
152 | "version": "1.0.4",
153 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
154 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
155 | },
156 | "ee-first": {
157 | "version": "1.1.1",
158 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
159 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
160 | },
161 | "encodeurl": {
162 | "version": "1.0.2",
163 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
164 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
165 | },
166 | "engine.io": {
167 | "version": "3.3.2",
168 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz",
169 | "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==",
170 | "requires": {
171 | "accepts": "~1.3.4",
172 | "base64id": "1.0.0",
173 | "cookie": "0.3.1",
174 | "debug": "~3.1.0",
175 | "engine.io-parser": "~2.1.0",
176 | "ws": "~6.1.0"
177 | },
178 | "dependencies": {
179 | "cookie": {
180 | "version": "0.3.1",
181 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
182 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
183 | },
184 | "debug": {
185 | "version": "3.1.0",
186 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
187 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
188 | "requires": {
189 | "ms": "2.0.0"
190 | }
191 | }
192 | }
193 | },
194 | "engine.io-client": {
195 | "version": "3.3.2",
196 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz",
197 | "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==",
198 | "requires": {
199 | "component-emitter": "1.2.1",
200 | "component-inherit": "0.0.3",
201 | "debug": "~3.1.0",
202 | "engine.io-parser": "~2.1.1",
203 | "has-cors": "1.1.0",
204 | "indexof": "0.0.1",
205 | "parseqs": "0.0.5",
206 | "parseuri": "0.0.5",
207 | "ws": "~6.1.0",
208 | "xmlhttprequest-ssl": "~1.5.4",
209 | "yeast": "0.1.2"
210 | },
211 | "dependencies": {
212 | "debug": {
213 | "version": "3.1.0",
214 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
215 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
216 | "requires": {
217 | "ms": "2.0.0"
218 | }
219 | }
220 | }
221 | },
222 | "engine.io-parser": {
223 | "version": "2.1.3",
224 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
225 | "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
226 | "requires": {
227 | "after": "0.8.2",
228 | "arraybuffer.slice": "~0.0.7",
229 | "base64-arraybuffer": "0.1.5",
230 | "blob": "0.0.5",
231 | "has-binary2": "~1.0.2"
232 | }
233 | },
234 | "escape-html": {
235 | "version": "1.0.3",
236 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
237 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
238 | },
239 | "etag": {
240 | "version": "1.8.1",
241 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
242 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
243 | },
244 | "express": {
245 | "version": "4.17.1",
246 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
247 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
248 | "requires": {
249 | "accepts": "~1.3.7",
250 | "array-flatten": "1.1.1",
251 | "body-parser": "1.19.0",
252 | "content-disposition": "0.5.3",
253 | "content-type": "~1.0.4",
254 | "cookie": "0.4.0",
255 | "cookie-signature": "1.0.6",
256 | "debug": "2.6.9",
257 | "depd": "~1.1.2",
258 | "encodeurl": "~1.0.2",
259 | "escape-html": "~1.0.3",
260 | "etag": "~1.8.1",
261 | "finalhandler": "~1.1.2",
262 | "fresh": "0.5.2",
263 | "merge-descriptors": "1.0.1",
264 | "methods": "~1.1.2",
265 | "on-finished": "~2.3.0",
266 | "parseurl": "~1.3.3",
267 | "path-to-regexp": "0.1.7",
268 | "proxy-addr": "~2.0.5",
269 | "qs": "6.7.0",
270 | "range-parser": "~1.2.1",
271 | "safe-buffer": "5.1.2",
272 | "send": "0.17.1",
273 | "serve-static": "1.14.1",
274 | "setprototypeof": "1.1.1",
275 | "statuses": "~1.5.0",
276 | "type-is": "~1.6.18",
277 | "utils-merge": "1.0.1",
278 | "vary": "~1.1.2"
279 | }
280 | },
281 | "finalhandler": {
282 | "version": "1.1.2",
283 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
284 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
285 | "requires": {
286 | "debug": "2.6.9",
287 | "encodeurl": "~1.0.2",
288 | "escape-html": "~1.0.3",
289 | "on-finished": "~2.3.0",
290 | "parseurl": "~1.3.3",
291 | "statuses": "~1.5.0",
292 | "unpipe": "~1.0.0"
293 | }
294 | },
295 | "forwarded": {
296 | "version": "0.1.2",
297 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
298 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
299 | },
300 | "fresh": {
301 | "version": "0.5.2",
302 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
303 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
304 | },
305 | "has-binary2": {
306 | "version": "1.0.3",
307 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
308 | "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
309 | "requires": {
310 | "isarray": "2.0.1"
311 | }
312 | },
313 | "has-cors": {
314 | "version": "1.1.0",
315 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
316 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
317 | },
318 | "http-errors": {
319 | "version": "1.7.2",
320 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
321 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
322 | "requires": {
323 | "depd": "~1.1.2",
324 | "inherits": "2.0.3",
325 | "setprototypeof": "1.1.1",
326 | "statuses": ">= 1.5.0 < 2",
327 | "toidentifier": "1.0.0"
328 | }
329 | },
330 | "iconv-lite": {
331 | "version": "0.4.24",
332 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
333 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
334 | "requires": {
335 | "safer-buffer": ">= 2.1.2 < 3"
336 | }
337 | },
338 | "indexof": {
339 | "version": "0.0.1",
340 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
341 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
342 | },
343 | "inherits": {
344 | "version": "2.0.3",
345 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
346 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
347 | },
348 | "ipaddr.js": {
349 | "version": "1.9.0",
350 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
351 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
352 | },
353 | "isarray": {
354 | "version": "2.0.1",
355 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
356 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
357 | },
358 | "media-typer": {
359 | "version": "0.3.0",
360 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
361 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
362 | },
363 | "merge-descriptors": {
364 | "version": "1.0.1",
365 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
366 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
367 | },
368 | "methods": {
369 | "version": "1.1.2",
370 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
371 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
372 | },
373 | "mime": {
374 | "version": "1.6.0",
375 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
376 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
377 | },
378 | "mime-db": {
379 | "version": "1.40.0",
380 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
381 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
382 | },
383 | "mime-types": {
384 | "version": "2.1.24",
385 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
386 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
387 | "requires": {
388 | "mime-db": "1.40.0"
389 | }
390 | },
391 | "ms": {
392 | "version": "2.0.0",
393 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
394 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
395 | },
396 | "negotiator": {
397 | "version": "0.6.2",
398 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
399 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
400 | },
401 | "object-assign": {
402 | "version": "4.1.0",
403 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
404 | "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A="
405 | },
406 | "object-component": {
407 | "version": "0.0.3",
408 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
409 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE="
410 | },
411 | "on-finished": {
412 | "version": "2.3.0",
413 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
414 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
415 | "requires": {
416 | "ee-first": "1.1.1"
417 | }
418 | },
419 | "parseqs": {
420 | "version": "0.0.5",
421 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
422 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
423 | "requires": {
424 | "better-assert": "~1.0.0"
425 | }
426 | },
427 | "parseuri": {
428 | "version": "0.0.5",
429 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
430 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
431 | "requires": {
432 | "better-assert": "~1.0.0"
433 | }
434 | },
435 | "parseurl": {
436 | "version": "1.3.3",
437 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
438 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
439 | },
440 | "path-to-regexp": {
441 | "version": "0.1.7",
442 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
443 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
444 | },
445 | "proxy-addr": {
446 | "version": "2.0.5",
447 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
448 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
449 | "requires": {
450 | "forwarded": "~0.1.2",
451 | "ipaddr.js": "1.9.0"
452 | }
453 | },
454 | "qs": {
455 | "version": "6.7.0",
456 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
457 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
458 | },
459 | "range-parser": {
460 | "version": "1.2.1",
461 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
462 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
463 | },
464 | "raw-body": {
465 | "version": "2.4.0",
466 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
467 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
468 | "requires": {
469 | "bytes": "3.1.0",
470 | "http-errors": "1.7.2",
471 | "iconv-lite": "0.4.24",
472 | "unpipe": "1.0.0"
473 | }
474 | },
475 | "safe-buffer": {
476 | "version": "5.1.2",
477 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
478 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
479 | },
480 | "safer-buffer": {
481 | "version": "2.1.2",
482 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
483 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
484 | },
485 | "send": {
486 | "version": "0.17.1",
487 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
488 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
489 | "requires": {
490 | "debug": "2.6.9",
491 | "depd": "~1.1.2",
492 | "destroy": "~1.0.4",
493 | "encodeurl": "~1.0.2",
494 | "escape-html": "~1.0.3",
495 | "etag": "~1.8.1",
496 | "fresh": "0.5.2",
497 | "http-errors": "~1.7.2",
498 | "mime": "1.6.0",
499 | "ms": "2.1.1",
500 | "on-finished": "~2.3.0",
501 | "range-parser": "~1.2.1",
502 | "statuses": "~1.5.0"
503 | },
504 | "dependencies": {
505 | "ms": {
506 | "version": "2.1.1",
507 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
508 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
509 | }
510 | }
511 | },
512 | "serve-static": {
513 | "version": "1.14.1",
514 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
515 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
516 | "requires": {
517 | "encodeurl": "~1.0.2",
518 | "escape-html": "~1.0.3",
519 | "parseurl": "~1.3.3",
520 | "send": "0.17.1"
521 | }
522 | },
523 | "setprototypeof": {
524 | "version": "1.1.1",
525 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
526 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
527 | },
528 | "socket.io": {
529 | "version": "2.2.0",
530 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz",
531 | "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==",
532 | "requires": {
533 | "debug": "~4.1.0",
534 | "engine.io": "~3.3.1",
535 | "has-binary2": "~1.0.2",
536 | "socket.io-adapter": "~1.1.0",
537 | "socket.io-client": "2.2.0",
538 | "socket.io-parser": "~3.3.0"
539 | },
540 | "dependencies": {
541 | "debug": {
542 | "version": "4.1.1",
543 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
544 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
545 | "requires": {
546 | "ms": "^2.1.1"
547 | }
548 | },
549 | "ms": {
550 | "version": "2.1.2",
551 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
552 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
553 | }
554 | }
555 | },
556 | "socket.io-adapter": {
557 | "version": "1.1.1",
558 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
559 | "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs="
560 | },
561 | "socket.io-client": {
562 | "version": "2.2.0",
563 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz",
564 | "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==",
565 | "requires": {
566 | "backo2": "1.0.2",
567 | "base64-arraybuffer": "0.1.5",
568 | "component-bind": "1.0.0",
569 | "component-emitter": "1.2.1",
570 | "debug": "~3.1.0",
571 | "engine.io-client": "~3.3.1",
572 | "has-binary2": "~1.0.2",
573 | "has-cors": "1.1.0",
574 | "indexof": "0.0.1",
575 | "object-component": "0.0.3",
576 | "parseqs": "0.0.5",
577 | "parseuri": "0.0.5",
578 | "socket.io-parser": "~3.3.0",
579 | "to-array": "0.1.4"
580 | },
581 | "dependencies": {
582 | "debug": {
583 | "version": "3.1.0",
584 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
585 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
586 | "requires": {
587 | "ms": "2.0.0"
588 | }
589 | }
590 | }
591 | },
592 | "socket.io-parser": {
593 | "version": "3.3.0",
594 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz",
595 | "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
596 | "requires": {
597 | "component-emitter": "1.2.1",
598 | "debug": "~3.1.0",
599 | "isarray": "2.0.1"
600 | },
601 | "dependencies": {
602 | "debug": {
603 | "version": "3.1.0",
604 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
605 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
606 | "requires": {
607 | "ms": "2.0.0"
608 | }
609 | }
610 | }
611 | },
612 | "statuses": {
613 | "version": "1.5.0",
614 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
615 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
616 | },
617 | "to-array": {
618 | "version": "0.1.4",
619 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
620 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
621 | },
622 | "toidentifier": {
623 | "version": "1.0.0",
624 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
625 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
626 | },
627 | "type-is": {
628 | "version": "1.6.18",
629 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
630 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
631 | "requires": {
632 | "media-typer": "0.3.0",
633 | "mime-types": "~2.1.24"
634 | }
635 | },
636 | "unpipe": {
637 | "version": "1.0.0",
638 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
639 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
640 | },
641 | "utils-merge": {
642 | "version": "1.0.1",
643 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
644 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
645 | },
646 | "vary": {
647 | "version": "1.1.2",
648 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
649 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
650 | },
651 | "ws": {
652 | "version": "6.1.4",
653 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
654 | "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
655 | "requires": {
656 | "async-limiter": "~1.0.0"
657 | }
658 | },
659 | "xmlhttprequest-ssl": {
660 | "version": "1.5.5",
661 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
662 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
663 | },
664 | "yeast": {
665 | "version": "0.1.2",
666 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
667 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
668 | }
669 | }
670 | }
671 |
--------------------------------------------------------------------------------