├── .gitignore
├── client
├── public
│ ├── robots.txt
│ ├── favicon.ico
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── index.html
├── src
│ ├── index.js
│ ├── apis
│ │ └── RestaurantFinder.js
│ ├── components
│ │ ├── Header.jsx
│ │ ├── StarRating.jsx
│ │ ├── AddRestaurant.jsx
│ │ ├── UpdateRestaurant.jsx
│ │ ├── AddReview.jsx
│ │ ├── Reviews.jsx
│ │ └── RestaurantList.jsx
│ ├── routes
│ │ ├── UpdatePage.jsx
│ │ ├── Home.jsx
│ │ └── RestaurantDetailPage.jsx
│ ├── context
│ │ └── RestaurantsContext.js
│ └── App.jsx
├── package.json
└── README.md
├── server
├── db
│ ├── index.js
│ └── db.sql
├── package.json
├── server.js
└── package-lock.json
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .env
--------------------------------------------------------------------------------
/client/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sanjeev-Thiyagarajan/PERN-STACK-DEPLOYMENT/HEAD/client/public/favicon.ico
--------------------------------------------------------------------------------
/client/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sanjeev-Thiyagarajan/PERN-STACK-DEPLOYMENT/HEAD/client/public/logo192.png
--------------------------------------------------------------------------------
/client/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sanjeev-Thiyagarajan/PERN-STACK-DEPLOYMENT/HEAD/client/public/logo512.png
--------------------------------------------------------------------------------
/server/db/index.js:
--------------------------------------------------------------------------------
1 | const { Pool } = require("pg");
2 |
3 | const pool = new Pool();
4 | module.exports = {
5 | query: (text, params) => pool.query(text, params),
6 | };
7 |
--------------------------------------------------------------------------------
/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import App from "./App";
4 |
5 | ReactDOM.render(, document.getElementById("root"));
6 |
--------------------------------------------------------------------------------
/client/src/apis/RestaurantFinder.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | const baseURL =
4 | process.env.NODE_ENV === "production"
5 | ? "/api/v1/restaurants"
6 | : "http://localhost:3001/api/v1/restaurants";
7 |
8 | export default axios.create({
9 | baseURL,
10 | });
11 |
--------------------------------------------------------------------------------
/client/src/components/Header.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Header = () => {
4 | return (
5 |
6 |
7 | Restaurant Finder
8 |
9 |
10 | );
11 | };
12 |
13 | export default Header;
14 |
--------------------------------------------------------------------------------
/client/src/routes/UpdatePage.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import UpdateRestaurant from "../components/UpdateRestaurant";
3 |
4 | const UpdatePage = () => {
5 | return (
6 |
7 |
Update Restaurant
8 |
9 |
10 | );
11 | };
12 |
13 | export default UpdatePage;
14 |
--------------------------------------------------------------------------------
/client/src/routes/Home.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Header from "../components/Header";
3 | import AddRestaurant from "../components/AddRestaurant";
4 | import RestaurantList from "../components/RestaurantList";
5 |
6 | const Home = () => {
7 | return (
8 |
13 | );
14 | };
15 |
16 | export default Home;
17 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node server.js",
8 | "dev": "nodemon server.js"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "cors": "^2.8.5",
15 | "dotenv": "^8.2.0",
16 | "express": "^4.17.1",
17 | "morgan": "^1.10.0",
18 | "nodemon": "^2.0.4",
19 | "pg": "^8.2.1"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/server/db/db.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE reviews (
2 | id BIGSERIAL NOT NULL PRIMARY KEY,
3 | restaurant_id BIGINT NOT NULL REFERENCES restaurants(id),
4 | name VARCHAR(50) NOT NULL,
5 | review TEXT NOT NULL,
6 | rating INT NOT NULL check(
7 | rating >= 1
8 | and rating <= 5
9 | )
10 | );
11 | select *
12 | from restaurants
13 | left join(
14 | select restaurant_id,
15 | count(*),
16 | TRUNC(AVG(rating, 1)) as average_rating
17 | from reviews
18 | group by restaurant_id
19 | ) reviews on restaurants.id = reviews.restaurant_id;
--------------------------------------------------------------------------------
/client/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/client/src/components/StarRating.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const StarRating = ({ rating }) => {
4 | //rating =4
5 | const stars = [];
6 | for (let i = 1; i <= 5; i++) {
7 | if (i <= rating) {
8 | stars.push();
9 | } else if (i === Math.ceil(rating) && !Number.isInteger(rating)) {
10 | stars.push();
11 | } else {
12 | stars.push();
13 | }
14 | }
15 | return <>{stars}>;
16 | };
17 |
18 | export default StarRating;
19 |
--------------------------------------------------------------------------------
/client/src/context/RestaurantsContext.js:
--------------------------------------------------------------------------------
1 | import React, { useState, createContext } from "react";
2 |
3 | export const RestaurantsContext = createContext();
4 |
5 | export const RestaurantsContextProvider = (props) => {
6 | const [restaurants, setRestaurants] = useState([]);
7 | const [selectedRestaurant, setSelectedRestaurant] = useState(null);
8 |
9 | const addRestaurants = (restaurant) => {
10 | setRestaurants([...restaurants, restaurant]);
11 | };
12 | return (
13 |
22 | {props.children}
23 |
24 | );
25 | };
26 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^4.2.4",
7 | "@testing-library/react": "^9.5.0",
8 | "@testing-library/user-event": "^7.2.1",
9 | "axios": "^0.19.2",
10 | "react": "^16.13.1",
11 | "react-dom": "^16.13.1",
12 | "react-router-dom": "^5.2.0",
13 | "react-scripts": "3.4.1"
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 | }
37 |
--------------------------------------------------------------------------------
/client/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
3 | import Home from "./routes/Home";
4 | import UpdatePage from "./routes/UpdatePage";
5 | import RestaurantDetailPage from "./routes/RestaurantDetailPage";
6 | import { RestaurantsContextProvider } from "./context/RestaurantsContext";
7 | const App = () => {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
19 |
24 |
25 |
26 |
27 |
28 | );
29 | };
30 |
31 | export default App;
32 |
--------------------------------------------------------------------------------
/client/src/routes/RestaurantDetailPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect } from "react";
2 | import { useParams } from "react-router-dom";
3 | import { RestaurantsContext } from "../context/RestaurantsContext";
4 | import RestaurantFinder from "../apis/RestaurantFinder";
5 | import StarRating from "../components/StarRating";
6 | import Reviews from "../components/Reviews";
7 | import AddReview from "../components/AddReview";
8 |
9 | const RestaurantDetailPage = () => {
10 | const { id } = useParams();
11 | const { selectedRestaurant, setSelectedRestaurant } = useContext(
12 | RestaurantsContext
13 | );
14 |
15 | useEffect(() => {
16 | const fetchData = async () => {
17 | try {
18 | const response = await RestaurantFinder.get(`/${id}`);
19 | console.log(response);
20 |
21 | setSelectedRestaurant(response.data.data);
22 | } catch (err) {
23 | console.log(err);
24 | }
25 | };
26 |
27 | fetchData();
28 | }, []);
29 | return (
30 |
31 | {selectedRestaurant && (
32 | <>
33 |
34 | {selectedRestaurant.restaurant.name}
35 |
36 |
37 |
38 |
39 | {selectedRestaurant.restaurant.count
40 | ? `(${selectedRestaurant.restaurant.count})`
41 | : "(0)"}
42 |
43 |
44 |
45 |
46 |
47 |
48 | >
49 | )}
50 |
51 | );
52 | };
53 |
54 | export default RestaurantDetailPage;
55 |
--------------------------------------------------------------------------------
/client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
24 |
28 |
37 | React App
38 |
39 |
40 |
41 |
42 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/client/src/components/AddRestaurant.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useContext } from "react";
2 | import RestaurantFinder from "../apis/RestaurantFinder";
3 | import { RestaurantsContext } from "../context/RestaurantsContext";
4 |
5 | const AddRestaurant = () => {
6 | const { addRestaurants } = useContext(RestaurantsContext);
7 | const [name, setName] = useState("");
8 | const [location, setLocation] = useState("");
9 | const [priceRange, setPriceRange] = useState("Price Range");
10 |
11 | const handleSubmit = async (e) => {
12 | e.preventDefault();
13 | try {
14 | const response = await RestaurantFinder.post("/", {
15 | name,
16 | location,
17 | price_range: priceRange,
18 | });
19 | console.log(response.data.data);
20 | addRestaurants(response.data.data.restaurant);
21 | } catch (err) {
22 | console.log(err);
23 | }
24 | };
25 | return (
26 |
71 | );
72 | };
73 |
74 | export default AddRestaurant;
75 |
--------------------------------------------------------------------------------
/client/src/components/UpdateRestaurant.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useContext, useEffect } from "react";
2 | import { useParams, useHistory } from "react-router-dom";
3 | import { RestaurantsContext } from "../context/RestaurantsContext";
4 | import RestaurantFinder from "../apis/RestaurantFinder";
5 |
6 | const UpdateRestaurant = (props) => {
7 | const { id } = useParams();
8 | let history = useHistory();
9 | const { restaurants } = useContext(RestaurantsContext);
10 | const [name, setName] = useState("");
11 | const [location, setLocation] = useState("");
12 | const [priceRange, setPriceRange] = useState("");
13 |
14 | useEffect(() => {
15 | const fetchData = async () => {
16 | const response = await RestaurantFinder.get(`/${id}`);
17 | console.log(response.data.data);
18 | setName(response.data.data.restaurant.name);
19 | setLocation(response.data.data.restaurant.location);
20 | setPriceRange(response.data.data.restaurant.price_range);
21 | };
22 |
23 | fetchData();
24 | }, []);
25 |
26 | const handleSubmit = async (e) => {
27 | e.preventDefault();
28 | const updatedRestaurant = await RestaurantFinder.put(`/${id}`, {
29 | name,
30 | location,
31 | price_range: priceRange,
32 | });
33 | history.push("/");
34 | };
35 |
36 | return (
37 |
79 | );
80 | };
81 |
82 | export default UpdateRestaurant;
83 |
--------------------------------------------------------------------------------
/client/src/components/AddReview.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import RestaurantFinder from "../apis/RestaurantFinder";
3 | import { useLocation, useParams, useHistory } from "react-router-dom";
4 |
5 | const AddReview = () => {
6 | const { id } = useParams();
7 | const location = useLocation();
8 | console.log(location);
9 | const history = useHistory();
10 | console.log(id);
11 |
12 | const [name, setName] = useState("");
13 | const [reviewText, setReviewText] = useState("");
14 | const [rating, setRating] = useState("Rating");
15 |
16 | const handleSubmitReview = async (e) => {
17 | e.preventDefault();
18 | try {
19 | const response = await RestaurantFinder.post(`/${id}/addReview`, {
20 | name,
21 | review: reviewText,
22 | rating,
23 | });
24 | history.push("/");
25 | history.push(location.pathname);
26 | } catch (err) {}
27 | };
28 | return (
29 |
78 | );
79 | };
80 |
81 | export default AddReview;
82 |
--------------------------------------------------------------------------------
/client/src/components/Reviews.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import StarRating from "./StarRating";
3 |
4 | const Reviews = ({ reviews }) => {
5 | return (
6 |
7 | {reviews.map((review) => {
8 | return (
9 |
14 |
15 | {review.name}
16 |
17 |
18 |
19 |
20 |
21 |
{review.review}
22 |
23 |
24 | );
25 | })}
26 | {/*
30 |
31 | Joan
32 |
33 |
34 |
35 |
36 |
37 |
This restaurant was awesome
38 |
39 |
40 |
41 |
45 |
46 | Joan
47 |
48 |
49 |
50 |
51 |
52 |
This restaurant was awesome
53 |
54 |
55 |
56 |
60 |
61 | Joan
62 |
63 |
64 |
65 |
66 |
67 |
This restaurant was awesome
68 |
69 |
70 |
74 |
75 | Joan
76 |
77 |
78 |
79 |
80 |
81 |
This restaurant was awesome
82 |
83 |
*/}
84 |
85 | );
86 | };
87 |
88 | export default Reviews;
89 |
--------------------------------------------------------------------------------
/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/server.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config();
2 | const express = require("express");
3 | const cors = require("cors");
4 | const db = require("./db");
5 |
6 | const morgan = require("morgan");
7 |
8 | const app = express();
9 |
10 | app.use(cors());
11 | app.use(express.json());
12 |
13 | // Get all Restaurants
14 | app.get("/api/v1/restaurants", async (req, res) => {
15 | try {
16 | //const results = await db.query("select * from restaurants");
17 | const restaurantRatingsData = await db.query(
18 | "select * from restaurants left join (select restaurant_id, COUNT(*), TRUNC(AVG(rating),1) as average_rating from reviews group by restaurant_id) reviews on restaurants.id = reviews.restaurant_id;"
19 | );
20 |
21 | res.status(200).json({
22 | status: "success",
23 | results: restaurantRatingsData.rows.length,
24 | data: {
25 | restaurants: restaurantRatingsData.rows,
26 | },
27 | });
28 | } catch (err) {
29 | console.log(err);
30 | }
31 | });
32 |
33 | //Get a Restaurant
34 | app.get("/api/v1/restaurants/:id", async (req, res) => {
35 | console.log(req.params.id);
36 |
37 | try {
38 | const restaurant = await db.query(
39 | "select * from restaurants left join (select restaurant_id, COUNT(*), TRUNC(AVG(rating),1) as average_rating from reviews group by restaurant_id) reviews on restaurants.id = reviews.restaurant_id where id = $1",
40 | [req.params.id]
41 | );
42 | // select * from restaurants wehre id = req.params.id
43 |
44 | const reviews = await db.query(
45 | "select * from reviews where restaurant_id = $1",
46 | [req.params.id]
47 | );
48 | console.log(reviews);
49 |
50 | res.status(200).json({
51 | status: "succes",
52 | data: {
53 | restaurant: restaurant.rows[0],
54 | reviews: reviews.rows,
55 | },
56 | });
57 | } catch (err) {
58 | console.log(err);
59 | }
60 | });
61 |
62 | // Create a Restaurant
63 |
64 | app.post("/api/v1/restaurants", async (req, res) => {
65 | console.log(req.body);
66 |
67 | try {
68 | const results = await db.query(
69 | "INSERT INTO restaurants (name, location, price_range) values ($1, $2, $3) returning *",
70 | [req.body.name, req.body.location, req.body.price_range]
71 | );
72 | console.log(results);
73 | res.status(201).json({
74 | status: "succes",
75 | data: {
76 | restaurant: results.rows[0],
77 | },
78 | });
79 | } catch (err) {
80 | console.log(err);
81 | }
82 | });
83 |
84 | // Update Restaurants
85 |
86 | app.put("/api/v1/restaurants/:id", async (req, res) => {
87 | try {
88 | const results = await db.query(
89 | "UPDATE restaurants SET name = $1, location = $2, price_range = $3 where id = $4 returning *",
90 | [req.body.name, req.body.location, req.body.price_range, req.params.id]
91 | );
92 |
93 | res.status(200).json({
94 | status: "succes",
95 | data: {
96 | retaurant: results.rows[0],
97 | },
98 | });
99 | } catch (err) {
100 | console.log(err);
101 | }
102 | console.log(req.params.id);
103 | console.log(req.body);
104 | });
105 |
106 | // Delete Restaurant
107 |
108 | app.delete("/api/v1/restaurants/:id", async (req, res) => {
109 | try {
110 | const results = db.query("DELETE FROM restaurants where id = $1", [
111 | req.params.id,
112 | ]);
113 | res.status(204).json({
114 | status: "sucess",
115 | });
116 | } catch (err) {
117 | console.log(err);
118 | }
119 | });
120 |
121 | app.post("/api/v1/restaurants/:id/addReview", async (req, res) => {
122 | try {
123 | const newReview = await db.query(
124 | "INSERT INTO reviews (restaurant_id, name, review, rating) values ($1, $2, $3, $4) returning *;",
125 | [req.params.id, req.body.name, req.body.review, req.body.rating]
126 | );
127 | console.log(newReview);
128 | res.status(201).json({
129 | status: "success",
130 | data: {
131 | review: newReview.rows[0],
132 | },
133 | });
134 | } catch (err) {
135 | console.log(err);
136 | }
137 | });
138 |
139 | const port = process.env.PORT || 3001;
140 | app.listen(port, () => {
141 | console.log(`server is up and listening on port ${port}`);
142 | });
143 |
--------------------------------------------------------------------------------
/client/src/components/RestaurantList.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useContext } from "react";
2 | import RestaurantFinder from "../apis/RestaurantFinder";
3 | import { RestaurantsContext } from "../context/RestaurantsContext";
4 | import { useHistory } from "react-router-dom";
5 | import StarRating from "./StarRating";
6 |
7 | const RestaurantList = (props) => {
8 | const { restaurants, setRestaurants } = useContext(RestaurantsContext);
9 | let history = useHistory();
10 | useEffect(() => {
11 | const fetchData = async () => {
12 | try {
13 | const response = await RestaurantFinder.get("/");
14 | console.log(response.data.data);
15 | setRestaurants(response.data.data.restaurants);
16 | } catch (err) {}
17 | };
18 |
19 | fetchData();
20 | }, []);
21 |
22 | const handleDelete = async (e, id) => {
23 | e.stopPropagation();
24 | try {
25 | const response = await RestaurantFinder.delete(`/${id}`);
26 | setRestaurants(
27 | restaurants.filter((restaurant) => {
28 | return restaurant.id !== id;
29 | })
30 | );
31 | } catch (err) {
32 | console.log(err);
33 | }
34 | };
35 |
36 | const handleUpdate = (e, id) => {
37 | e.stopPropagation();
38 | history.push(`/restaurants/${id}/update`);
39 | };
40 |
41 | const handleRestaurantSelect = (id) => {
42 | history.push(`/restaurants/${id}`);
43 | };
44 |
45 | const renderRating = (restaurant) => {
46 | if (!restaurant.count) {
47 | return 0 reviews;
48 | }
49 | return (
50 | <>
51 |
52 | ({restaurant.count})
53 | >
54 | );
55 | };
56 |
57 | return (
58 |
59 |
60 |
61 |
62 | | Restaurant |
63 | Location |
64 | Price Range |
65 | Ratings |
66 | Edit |
67 | Delete |
68 |
69 |
70 |
71 | {restaurants &&
72 | restaurants.map((restaurant) => {
73 | return (
74 | handleRestaurantSelect(restaurant.id)}
76 | key={restaurant.id}
77 | >
78 | | {restaurant.name} |
79 | {restaurant.location} |
80 | {"$".repeat(restaurant.price_range)} |
81 | {renderRating(restaurant)} |
82 |
83 |
89 | |
90 |
91 |
97 | |
98 |
99 | );
100 | })}
101 | {/*
102 | | mcdonalds |
103 | New YOrk |
104 | $$ |
105 | Rating |
106 |
107 |
108 | |
109 |
110 |
111 | |
112 |
113 |
114 |
115 | | mcdonalds |
116 | New YOrk |
117 | $$ |
118 | Rating |
119 |
120 |
121 | |
122 |
123 |
124 | |
125 |
*/}
126 |
127 |
128 |
129 | );
130 | };
131 |
132 | export default RestaurantList;
133 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Deploying PERN stack on Ubuntu 20.04
2 |
3 | > Detailed step by step procedure to deploying PERN(Postgres, Express, React, Node) stack on Ubuntu 20.04 with NGINX and SSL
4 |
5 | ## 1. Install and Configure PostgreSQL
6 |
7 | Update packages
8 | ```
9 | sudo apt update && sudo apt upgrade -y
10 | ```
11 |
12 | install PostgreSQL
13 | ```
14 | sudo apt install postgresql postgresql-contrib -y
15 | ```
16 |
17 | PostgreSQL will create an initial user called `postgres`. In addition, PostgreSQL uses what's reffered to as peer authentication for local connections. This means that PostgreSQL obtains the username from the linux kernel and uses that to connect to the database. This requires that any user configured on postgres to have an equivalent user defined on Ubuntu. Postgres installation will have automatically created a `postgres` user on Ubuntu as well to allow local connection. this can be verified by running the command:
18 |
19 | ```
20 | ubuntu@ip-172-31-20-1:~$ sudo cat /etc/passwd | grep -i postgres
21 | postgres:x:113:120:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
22 | ```
23 |
24 | To connect to Postgres, switch to the `postgres` user and run psql:
25 |
26 | ```
27 | ubuntu@ip-172-31-20-1:~$ sudo -i -u postgres
28 | postgres@ip-172-31-20-1:~$ psql
29 | psql (12.4 (Ubuntu 12.4-0ubuntu0.20.04.1))
30 | Type "help" for help.
31 |
32 | postgres=#
33 | ```
34 |
35 | For this tutorial, the node process process will be run under the `ubuntu` user and for the sake of simplicity, an `ubuntu` user will be created on Postgres as well. If you want to use a different user feel free to create a different user in postgres.
36 |
37 | To create a Postgres user run the following command which will give an interactive prompt for configuring the new user. For the sake of simplicity, the ubuntu user will be a superuser, which is the equivalent of being a root user on linux. The super user will have the ability to create/delete/modify databases and users.
38 |
39 | ```
40 | postgres@ip-172-31-20-1:~$ createuser --interactive
41 | Enter name of role to add: ubuntu
42 | Shall the new role be a superuser? (y/n) y
43 | ```
44 |
45 | login to postgres using the `postgres` user for now to verify the new `ubuntu` user was created successfully
46 |
47 | ```
48 | postgres@ip-172-31-20-1:~$ psql
49 | psql (12.4 (Ubuntu 12.4-0ubuntu0.20.04.1))
50 | Type "help" for help.
51 |
52 | postgres=# \du
53 | List of roles
54 | Role name | Attributes | Member of
55 | -----------+------------------------------------------------------------+-----------
56 | postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
57 | sanjeev | Superuser, Create role, Create DB | {}
58 | test | | {}
59 | test1 | Superuser, Create role, Create DB | {}
60 | ubuntu | Superuser, Create role, Create DB | {}
61 |
62 | postgres=#
63 | ```
64 |
65 | Exit out of the psql by running `\q` and also exit out of the `postgres` user by running `exit` on the command line
66 |
67 | Let's try to run `psql` as the ubuntu user now. An error similar to the one below should be observed
68 |
69 | ```
70 | ubuntu@ip-172-31-20-1:~$ psql
71 | psql: error: could not connect to server: FATAL: database "ubuntu" does not exist
72 | ```
73 |
74 | The reason for this is that Postgres by default tries to connect to a database that is the same name as the user. Since the user is `ubuntu` it tries to connect to a database called `ubuntu` as well which does not exist. We can go in and create a database called `ubuntu` so that it will automtically connect, however I find this unnecessry. Instead we can pass in the `-d` flag and connect to a database that we know exists like the `postgres`
75 |
76 | ```
77 | psql -d postgres
78 | ```
79 |
80 | Right now the `ubuntu` user in Postgres does not have a password associated with it. We will need to add a password:
81 |
82 | ```
83 | ubuntu@ip-172-31-20-1:~$ psql -d postgres
84 | psql (12.4 (Ubuntu 12.4-0ubuntu0.20.04.1))
85 | Type "help" for help.
86 |
87 | postgres=# \q
88 | ubuntu@ip-172-31-20-1:~$ psql -d postgres
89 | psql (12.4 (Ubuntu 12.4-0ubuntu0.20.04.1))
90 | Type "help" for help.
91 |
92 | postgres=# ALTER USER ubuntu PASSWORD 'password';
93 | ALTER ROLE
94 | postgres=#
95 | ```
96 |
97 | ## 2. Migrate Database Scheme & data
98 | As with most sql database PostgreSQL allows us to easily copy our database schema and data from our local development postgres instance and copy it over to the Postgres isntance running in our production server.
99 |
100 | On your local dev machine, open up a terminal and run:
101 |
102 | ```
103 | pg_dump -U postgres -f yelp.pgsql -C yelp
104 | ```
105 | The `-U` flag specifies the user u want to login as, if you are using a different username, update it accordingly.
106 | The `-f yelp.pgsql` flag will write the database schema and data to a file called `yelp.pgsql` in the current directory
107 | `-C` flag add the create database command to the file as well
108 | `yelp` is the name of the database in our local dev server that we want to dump. If your database is called something else update that accordingly. If you leave out the database name alltogether it will dump all databases
109 |
110 | Copy the yelp.pgsql file to the production server
111 | ```
112 | scp -i [path to pem file] [path to yelp.pgsql] username@[server-ip]:[directory to copy file to]
113 | ```
114 |
115 | In this example the pem file and yelp.gsql file are located in the current directory and my server ip is `1.1.1.1` and the username is `ubuntu`
116 |
117 | ```
118 | scp -i yelp.pem yelp.pgsql ubuntu@1.1.1.1:/home/ubuntu/
119 | ```
120 |
121 | Login to the production server and create a database called `yelp`
122 | ```
123 | ubuntu@ip-172-31-20-1:~$ psql -d yelp
124 | postgres=# create database yelp;
125 | CREATE DATABASE
126 | ```
127 |
128 | Import the database schema & data from the `yelp.pgsql` file
129 |
130 | ```
131 | psql yelp < /home/ubuntu/yelp.pgsql
132 | ```
133 |
134 | login to the yelp database and verify that everything looks ok
135 | ```
136 | ubuntu@ip-172-31-20-1:~$ psql -d yelp
137 | psql (12.4 (Ubuntu 12.4-0ubuntu0.20.04.1))
138 | Type "help" for help.
139 |
140 | yelp=# \d
141 | List of relations
142 | Schema | Name | Type | Owner
143 | --------+--------------------+----------+----------
144 | public | restaurants | table | postgres
145 | public | restaurants_id_seq | sequence | postgres
146 | public | reviews | table | postgres
147 | public | reviews_id_seq | sequence | postgres
148 | (4 rows)
149 |
150 | yelp=# select * from restaurants;
151 | id | name | location | price_range
152 | ----+--------------------------+-----------------+-------------
153 | 2 | taco bell | san fran | 3
154 | 3 | taco bell | New York | 4
155 | 4 | cheesecake factory | dallas | 2
156 | 5 | cheesecake factory | dallas | 2
157 | 6 | cheesecake factory | houston | 2
158 | 10 | chiptle | virgini | 1
159 | 11 | chiptle | virgini | 1
160 | 13 | california pizza kitchen | vegas | 1
161 | 1 | wendys | Lincoln | 4
162 | 14 | california pizza kitchen | New mexico city | 3
163 | (10 rows)
164 |
165 | yelp=#
166 | ```
167 |
168 |
169 | ## 3. Copy github repo to sever
170 |
171 | Find a place to store your application code. In this example in the `ubuntu` home directory a new directory called `apps` will be created. Within the new `apps` directory another directory called `yelp-app`. Feel free to store your application code anywhere you see fit
172 |
173 | ```
174 | cd ~
175 | mkdir apps
176 | cd apps
177 | mkdir yelp-app
178 | ```
179 |
180 | move inside the `yelp-app` directory and clone the project repo
181 | ```
182 | cd yelp-app
183 | git clone https://github.com/Sanjeev-Thiyagarajan/PERN-STACK-DEPLOYMENT.git .
184 | ```
185 |
186 | ## 4. Install Node
187 | To install Node on Ubuntu follow the steps detailed in:
188 | https://github.com/nodesource/distributions/blob/master/README.md
189 |
190 | ```
191 | curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
192 | sudo apt-get install -y nodejs
193 | ```
194 |
195 | ## 5. Install and Configure PM2
196 | We never want to run *node* directly in production. Instead we want to use a process manager like PM2 to handle running our backend server. PM2 will be responsible for restarting the App if/when it crashes :grin:
197 |
198 | ```
199 | sudo npm install pm2 -g
200 | ```
201 | Point pm2 to the location of the server.js file so it can start the app. We can add the `--name` flag to give the process a descriptive name
202 | ```
203 | pm2 start /home/ubuntu/apps/yelp-app/server/server.js --name yelp-app
204 | ```
205 |
206 | Configure PM2 to automatically startup the process after a reboot
207 |
208 | ```
209 | ubuntu@ip-172-31-20-1:~$ pm2 startup
210 | [PM2] Init System found: systemd
211 | [PM2] To setup the Startup Script, copy/paste the following command:
212 | sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu
213 | ```
214 | The output above gives you a specific command to run, copy and paste it into the terminal. The command given will be different on your machine depending on the username, so do not copy the output above, instead run the command that is given in your output.
215 |
216 | ```
217 | sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu
218 | ```
219 |
220 | Verify that the App is running
221 |
222 | ```
223 | pm2 status
224 | ```
225 | After verify App is running, save the current list of processes so that the same processes are started during bootup. If the list of processes ever changes in the future, you'll want to do another `pm2 save`
226 |
227 | ```
228 | pm2 save
229 | ```
230 |
231 | ## 6. Deploy React Frontend
232 | Navigate to the client directory in our App code and run `npm run build`.
233 |
234 | This will create a finalized production ready version of our react frontent in directory called `build`. The build folder is what the NGINX server will be configured to serve.
235 |
236 | ```
237 | ubuntu@ip-172-31-20-1:~/apps/yelp-app/client$ ls
238 | README.md build node_modules package-lock.json package.json public src
239 | ubuntu@ip-172-31-20-1:~/apps/yelp-app/client$ cd build/
240 | ubuntu@ip-172-31-20-1:~/apps/yelp-app/client/build$ ls
241 | asset-manifest.json favicon.ico index.html logo192.png logo512.png manifest.json precache-manifest.ee13f4c95d9882a5229da70669bb264c.js robots.txt service-worker.js static
242 | ubuntu@ip-172-31-20-1:~/apps/yelp-app/client/build$
243 | ```
244 |
245 | ## 7. Install and Configure NGINX
246 |
247 | Install and enable NGINX
248 | ```
249 | sudo apt install nginx -y
250 | sudo systemctl enable nginx
251 | ```
252 |
253 | NGINX is a feature-rich webserver that can serve multiple websites/web-apps on one machine. Each website that NGINX is responsible for serving needs to have a seperate server block configured for it.
254 |
255 | Navigate to '/etc/nginx/sites-available'
256 |
257 | ```
258 | cd /etc/nginx/sites-available
259 | ```
260 |
261 | There should be a server block called `default`
262 |
263 | ```
264 | ubuntu@ip-172-31-20-1:/etc/nginx/sites-available$ ls
265 | default
266 | ```
267 | The default server block is what will be responsible for handling requests that don't match any other server blocks. Right now if you navigate to your server ip, you will see a pretty bland html page that says NGINX is installed. That is the `default` server block in action.
268 |
269 | We will need to configure a new server block for our website. To do that let's create a new file in `/etc/nginx/sites-available/` directory. We can call this file whatever you want, but I recommend that you name it the same name as your domain name for your app. In this example my website will be hosted at *sanjeev.xyz* so I will also name the new file `sanjeev.xyz`. But instead of creating a brand new file, since most of the configs will be fairly similar to the `default` server block, I recommend copying the `default` config.
270 |
271 | ```
272 | cd /etc/nginx/sites-available
273 | sudo cp default sanjeev.xyz
274 | ```
275 |
276 | open the new server block file `sanjeev.xyz` and modify it so it matches below:
277 |
278 | ```
279 | server {
280 | listen 80;
281 | listen [::]:80;
282 |
283 | root /home/ubuntu/apps/yelp-app/client/build;
284 |
285 | # Add index.php to the list if you are using PHP
286 | index index.html index.htm index.nginx-debian.html;
287 |
288 | server_name sanjeev.xyz www.sanjeev.xyz;
289 |
290 | location / {
291 | try_files $uri /index.html;
292 | }
293 |
294 | location /api {
295 | proxy_pass http://localhost:3001;
296 | proxy_http_version 1.1;
297 | proxy_set_header Upgrade $http_upgrade;
298 | proxy_set_header Connection 'upgrade';
299 | proxy_set_header Host $host;
300 | proxy_cache_bypass $http_upgrade;
301 | }
302 |
303 | }
304 | ```
305 |
306 | **Let's go over what each line does**
307 |
308 | The first two lines `listen 80` and `listen [::]:80;` tell nginx to listen for traffic on port 80 which is the default port for http traffic. Note that I removed the `default_server` keyword on these lines. If you want this server block to be the default then keep it in
309 |
310 | `root /home/ubuntu/apps/yelp-app/client/build;` tells nginx the path to the index.html file it will server. Here we passed the path to the build directory in our react app code. This directory has the finalized html/js/css files for the frontend.
311 |
312 | `server_name sanjeev.xyz www.sanjeev.xyz;` tells nginx what domain names it should listen for. Make sure to replace this with your specific domains. If you don't have a domain then you can put the ip address of your ubuntu server.
313 |
314 | The configuration block below is needed due to the fact that React is a Singe-Page-App. So if a user directly goes to a url that is not the root url like `https://sanjeev.xyz/restaurants/4` you will get a 404 cause NGINX has not been configured to handle any path ohter than the `/`. This config block tells nginx to redirect everything back to the `/` path so that react can then handle the routing.
315 |
316 | ```
317 | location / {
318 | try_files $uri /index.html;
319 | }
320 | ```
321 |
322 | The last section is so that nginx can handle traffic destined to the backend. Notice the location is for `/api`. So any url with a path of `/api` will automatically follow the instructions associated with this config block. The first line in the config block `proxy_pass http://localhost:3001;` tells nginx to redirect it to the localhost on port 3001 which is the port that our backend process is running on. This is how traffic gets forwarded to the Node backend. If you are using a different port, make sure to update that in this line.
323 |
324 | **Enable the new site**
325 | ```
326 | sudo ln -s /etc/nginx/sites-available/sanjeev.xyz /etc/nginx/sites-enabled/
327 | systemctl restart nginx
328 | ```
329 |
330 | ## 8. Configure Environment Variables
331 | We now need to make sure that all of the proper environment variables are setup on our production Ubuntu Server. In our development environment, we made use of a package called dotenv to load up environment variables. In the production environment the environment variables are going to be set on the OS instead of within Node.
332 |
333 | Create a file called `.env` in `/home/ubuntu/`. The file does not need to be named `.env` and it does not need to be stored in `/home/ubuntu`, these were just the name/location of my choosing. The only thing I recommend avoid doing is placing the file in the same directory as the app code as we want to make sure we don't accidentally check our environment variables into git and end up exposing our credentials.
334 |
335 | Within the .env file paste all the required environment variables
336 |
337 | ```
338 | PORT=3001
339 | PGUSER=postgres
340 | PGHOST=localhost
341 | PGPASSWORD=password123
342 | PGDATABASE=yelp
343 | PGPORT=5432
344 | NODE_ENV=production
345 | ```
346 |
347 | You'll notice I also set `NODE_ENV=production`. Although its not required for this example project, it is common practice. For man other projects(depending on how the backend is setup) they may require this to be set in a production environment.
348 |
349 |
350 | In the `/home/ubuntu/.profile` add the following line to the bottom of the file
351 |
352 | ```
353 | set -o allexport; source /home/ubuntu/.env; set +o allexport
354 | ```
355 |
356 | For these changes to take affect, close the current terminal session and open a new one.
357 |
358 | Verify that the environment variables are set by running the `printenv`
359 |
360 | ```
361 | # printenv
362 | ```
363 |
364 | ## 9. Enable Firewall
365 |
366 | ```
367 | sudo ufw status
368 | sudo ufw allow ssh
369 | sudo ufw allow http
370 | sudo ufw allow https
371 | sudo ufw enable
372 | sudo ufw status
373 | ```
374 |
375 | ## 10. Enable SSL with Let's Encrypt
376 | Nowadays almost all websites use HTTPS exclusively. Let's use Let's Encrypt to generate SSL certificates and also configure NGINX to use these certificates and redirect http traffic to HTTPS.
377 |
378 | The step by step procedure is listed at:
379 | https://certbot.eff.org/lets-encrypt/ubuntufocal-nginx.html
380 |
381 |
382 | Install Certbot
383 |
384 | ```
385 | sudo snap install --classic certbot
386 | ```
387 |
388 | Prepare the Certbot command
389 |
390 | ```
391 | sudo ln -s /snap/bin/certbot /usr/bin/certbot
392 | ```
393 |
394 | Get and install certificates using interactive prompt
395 |
396 | ```
397 | sudo certbot --nginx
398 | ```
399 |
400 | ## Authors
401 | * **Sanjeev Thiyagarajan** - *CEO of Nothing*
402 |
403 |
--------------------------------------------------------------------------------
/server/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@sindresorhus/is": {
8 | "version": "0.14.0",
9 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
10 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ=="
11 | },
12 | "@szmarczak/http-timer": {
13 | "version": "1.1.2",
14 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
15 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
16 | "requires": {
17 | "defer-to-connect": "^1.0.1"
18 | }
19 | },
20 | "@types/color-name": {
21 | "version": "1.1.1",
22 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
23 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
24 | },
25 | "abbrev": {
26 | "version": "1.1.1",
27 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
28 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
29 | },
30 | "accepts": {
31 | "version": "1.3.7",
32 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
33 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
34 | "requires": {
35 | "mime-types": "~2.1.24",
36 | "negotiator": "0.6.2"
37 | }
38 | },
39 | "ansi-align": {
40 | "version": "3.0.0",
41 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
42 | "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
43 | "requires": {
44 | "string-width": "^3.0.0"
45 | },
46 | "dependencies": {
47 | "string-width": {
48 | "version": "3.1.0",
49 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
50 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
51 | "requires": {
52 | "emoji-regex": "^7.0.1",
53 | "is-fullwidth-code-point": "^2.0.0",
54 | "strip-ansi": "^5.1.0"
55 | }
56 | }
57 | }
58 | },
59 | "ansi-regex": {
60 | "version": "4.1.0",
61 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
62 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
63 | },
64 | "ansi-styles": {
65 | "version": "4.2.1",
66 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
67 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
68 | "requires": {
69 | "@types/color-name": "^1.1.1",
70 | "color-convert": "^2.0.1"
71 | }
72 | },
73 | "anymatch": {
74 | "version": "3.1.1",
75 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
76 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
77 | "requires": {
78 | "normalize-path": "^3.0.0",
79 | "picomatch": "^2.0.4"
80 | }
81 | },
82 | "array-flatten": {
83 | "version": "1.1.1",
84 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
85 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
86 | },
87 | "balanced-match": {
88 | "version": "1.0.0",
89 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
90 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
91 | },
92 | "basic-auth": {
93 | "version": "2.0.1",
94 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
95 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
96 | "requires": {
97 | "safe-buffer": "5.1.2"
98 | }
99 | },
100 | "binary-extensions": {
101 | "version": "2.0.0",
102 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
103 | "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow=="
104 | },
105 | "body-parser": {
106 | "version": "1.19.0",
107 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
108 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
109 | "requires": {
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 | },
122 | "boxen": {
123 | "version": "4.2.0",
124 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz",
125 | "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==",
126 | "requires": {
127 | "ansi-align": "^3.0.0",
128 | "camelcase": "^5.3.1",
129 | "chalk": "^3.0.0",
130 | "cli-boxes": "^2.2.0",
131 | "string-width": "^4.1.0",
132 | "term-size": "^2.1.0",
133 | "type-fest": "^0.8.1",
134 | "widest-line": "^3.1.0"
135 | }
136 | },
137 | "brace-expansion": {
138 | "version": "1.1.11",
139 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
140 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
141 | "requires": {
142 | "balanced-match": "^1.0.0",
143 | "concat-map": "0.0.1"
144 | }
145 | },
146 | "braces": {
147 | "version": "3.0.2",
148 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
149 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
150 | "requires": {
151 | "fill-range": "^7.0.1"
152 | }
153 | },
154 | "buffer-writer": {
155 | "version": "2.0.0",
156 | "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
157 | "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
158 | },
159 | "bytes": {
160 | "version": "3.1.0",
161 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
162 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
163 | },
164 | "cacheable-request": {
165 | "version": "6.1.0",
166 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
167 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
168 | "requires": {
169 | "clone-response": "^1.0.2",
170 | "get-stream": "^5.1.0",
171 | "http-cache-semantics": "^4.0.0",
172 | "keyv": "^3.0.0",
173 | "lowercase-keys": "^2.0.0",
174 | "normalize-url": "^4.1.0",
175 | "responselike": "^1.0.2"
176 | },
177 | "dependencies": {
178 | "get-stream": {
179 | "version": "5.1.0",
180 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
181 | "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
182 | "requires": {
183 | "pump": "^3.0.0"
184 | }
185 | },
186 | "lowercase-keys": {
187 | "version": "2.0.0",
188 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
189 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
190 | }
191 | }
192 | },
193 | "camelcase": {
194 | "version": "5.3.1",
195 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
196 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
197 | },
198 | "chalk": {
199 | "version": "3.0.0",
200 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
201 | "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
202 | "requires": {
203 | "ansi-styles": "^4.1.0",
204 | "supports-color": "^7.1.0"
205 | },
206 | "dependencies": {
207 | "has-flag": {
208 | "version": "4.0.0",
209 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
210 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
211 | },
212 | "supports-color": {
213 | "version": "7.1.0",
214 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
215 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
216 | "requires": {
217 | "has-flag": "^4.0.0"
218 | }
219 | }
220 | }
221 | },
222 | "chokidar": {
223 | "version": "3.4.0",
224 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
225 | "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
226 | "requires": {
227 | "anymatch": "~3.1.1",
228 | "braces": "~3.0.2",
229 | "fsevents": "~2.1.2",
230 | "glob-parent": "~5.1.0",
231 | "is-binary-path": "~2.1.0",
232 | "is-glob": "~4.0.1",
233 | "normalize-path": "~3.0.0",
234 | "readdirp": "~3.4.0"
235 | }
236 | },
237 | "ci-info": {
238 | "version": "2.0.0",
239 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
240 | "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
241 | },
242 | "cli-boxes": {
243 | "version": "2.2.0",
244 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz",
245 | "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w=="
246 | },
247 | "clone-response": {
248 | "version": "1.0.2",
249 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
250 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
251 | "requires": {
252 | "mimic-response": "^1.0.0"
253 | }
254 | },
255 | "color-convert": {
256 | "version": "2.0.1",
257 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
258 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
259 | "requires": {
260 | "color-name": "~1.1.4"
261 | }
262 | },
263 | "color-name": {
264 | "version": "1.1.4",
265 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
266 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
267 | },
268 | "concat-map": {
269 | "version": "0.0.1",
270 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
271 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
272 | },
273 | "configstore": {
274 | "version": "5.0.1",
275 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
276 | "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
277 | "requires": {
278 | "dot-prop": "^5.2.0",
279 | "graceful-fs": "^4.1.2",
280 | "make-dir": "^3.0.0",
281 | "unique-string": "^2.0.0",
282 | "write-file-atomic": "^3.0.0",
283 | "xdg-basedir": "^4.0.0"
284 | }
285 | },
286 | "content-disposition": {
287 | "version": "0.5.3",
288 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
289 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
290 | "requires": {
291 | "safe-buffer": "5.1.2"
292 | }
293 | },
294 | "content-type": {
295 | "version": "1.0.4",
296 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
297 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
298 | },
299 | "cookie": {
300 | "version": "0.4.0",
301 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
302 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
303 | },
304 | "cookie-signature": {
305 | "version": "1.0.6",
306 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
307 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
308 | },
309 | "cors": {
310 | "version": "2.8.5",
311 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
312 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
313 | "requires": {
314 | "object-assign": "^4",
315 | "vary": "^1"
316 | }
317 | },
318 | "crypto-random-string": {
319 | "version": "2.0.0",
320 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
321 | "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="
322 | },
323 | "debug": {
324 | "version": "2.6.9",
325 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
326 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
327 | "requires": {
328 | "ms": "2.0.0"
329 | }
330 | },
331 | "decompress-response": {
332 | "version": "3.3.0",
333 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
334 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
335 | "requires": {
336 | "mimic-response": "^1.0.0"
337 | }
338 | },
339 | "deep-extend": {
340 | "version": "0.6.0",
341 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
342 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
343 | },
344 | "defer-to-connect": {
345 | "version": "1.1.3",
346 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
347 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="
348 | },
349 | "depd": {
350 | "version": "1.1.2",
351 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
352 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
353 | },
354 | "destroy": {
355 | "version": "1.0.4",
356 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
357 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
358 | },
359 | "dot-prop": {
360 | "version": "5.2.0",
361 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
362 | "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
363 | "requires": {
364 | "is-obj": "^2.0.0"
365 | }
366 | },
367 | "dotenv": {
368 | "version": "8.2.0",
369 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
370 | "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
371 | },
372 | "duplexer3": {
373 | "version": "0.1.4",
374 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
375 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
376 | },
377 | "ee-first": {
378 | "version": "1.1.1",
379 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
380 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
381 | },
382 | "emoji-regex": {
383 | "version": "7.0.3",
384 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
385 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
386 | },
387 | "encodeurl": {
388 | "version": "1.0.2",
389 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
390 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
391 | },
392 | "end-of-stream": {
393 | "version": "1.4.4",
394 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
395 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
396 | "requires": {
397 | "once": "^1.4.0"
398 | }
399 | },
400 | "escape-goat": {
401 | "version": "2.1.1",
402 | "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
403 | "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q=="
404 | },
405 | "escape-html": {
406 | "version": "1.0.3",
407 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
408 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
409 | },
410 | "etag": {
411 | "version": "1.8.1",
412 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
413 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
414 | },
415 | "express": {
416 | "version": "4.17.1",
417 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
418 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
419 | "requires": {
420 | "accepts": "~1.3.7",
421 | "array-flatten": "1.1.1",
422 | "body-parser": "1.19.0",
423 | "content-disposition": "0.5.3",
424 | "content-type": "~1.0.4",
425 | "cookie": "0.4.0",
426 | "cookie-signature": "1.0.6",
427 | "debug": "2.6.9",
428 | "depd": "~1.1.2",
429 | "encodeurl": "~1.0.2",
430 | "escape-html": "~1.0.3",
431 | "etag": "~1.8.1",
432 | "finalhandler": "~1.1.2",
433 | "fresh": "0.5.2",
434 | "merge-descriptors": "1.0.1",
435 | "methods": "~1.1.2",
436 | "on-finished": "~2.3.0",
437 | "parseurl": "~1.3.3",
438 | "path-to-regexp": "0.1.7",
439 | "proxy-addr": "~2.0.5",
440 | "qs": "6.7.0",
441 | "range-parser": "~1.2.1",
442 | "safe-buffer": "5.1.2",
443 | "send": "0.17.1",
444 | "serve-static": "1.14.1",
445 | "setprototypeof": "1.1.1",
446 | "statuses": "~1.5.0",
447 | "type-is": "~1.6.18",
448 | "utils-merge": "1.0.1",
449 | "vary": "~1.1.2"
450 | }
451 | },
452 | "fill-range": {
453 | "version": "7.0.1",
454 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
455 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
456 | "requires": {
457 | "to-regex-range": "^5.0.1"
458 | }
459 | },
460 | "finalhandler": {
461 | "version": "1.1.2",
462 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
463 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
464 | "requires": {
465 | "debug": "2.6.9",
466 | "encodeurl": "~1.0.2",
467 | "escape-html": "~1.0.3",
468 | "on-finished": "~2.3.0",
469 | "parseurl": "~1.3.3",
470 | "statuses": "~1.5.0",
471 | "unpipe": "~1.0.0"
472 | }
473 | },
474 | "forwarded": {
475 | "version": "0.1.2",
476 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
477 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
478 | },
479 | "fresh": {
480 | "version": "0.5.2",
481 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
482 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
483 | },
484 | "fsevents": {
485 | "version": "2.1.3",
486 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
487 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
488 | "optional": true
489 | },
490 | "get-stream": {
491 | "version": "4.1.0",
492 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
493 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
494 | "requires": {
495 | "pump": "^3.0.0"
496 | }
497 | },
498 | "glob-parent": {
499 | "version": "5.1.1",
500 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
501 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
502 | "requires": {
503 | "is-glob": "^4.0.1"
504 | }
505 | },
506 | "global-dirs": {
507 | "version": "2.0.1",
508 | "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz",
509 | "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==",
510 | "requires": {
511 | "ini": "^1.3.5"
512 | }
513 | },
514 | "got": {
515 | "version": "9.6.0",
516 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
517 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
518 | "requires": {
519 | "@sindresorhus/is": "^0.14.0",
520 | "@szmarczak/http-timer": "^1.1.2",
521 | "cacheable-request": "^6.0.0",
522 | "decompress-response": "^3.3.0",
523 | "duplexer3": "^0.1.4",
524 | "get-stream": "^4.1.0",
525 | "lowercase-keys": "^1.0.1",
526 | "mimic-response": "^1.0.1",
527 | "p-cancelable": "^1.0.0",
528 | "to-readable-stream": "^1.0.0",
529 | "url-parse-lax": "^3.0.0"
530 | }
531 | },
532 | "graceful-fs": {
533 | "version": "4.2.4",
534 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
535 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
536 | },
537 | "has-flag": {
538 | "version": "3.0.0",
539 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
540 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
541 | },
542 | "has-yarn": {
543 | "version": "2.1.0",
544 | "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
545 | "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw=="
546 | },
547 | "http-cache-semantics": {
548 | "version": "4.1.0",
549 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
550 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
551 | },
552 | "http-errors": {
553 | "version": "1.7.2",
554 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
555 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
556 | "requires": {
557 | "depd": "~1.1.2",
558 | "inherits": "2.0.3",
559 | "setprototypeof": "1.1.1",
560 | "statuses": ">= 1.5.0 < 2",
561 | "toidentifier": "1.0.0"
562 | }
563 | },
564 | "iconv-lite": {
565 | "version": "0.4.24",
566 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
567 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
568 | "requires": {
569 | "safer-buffer": ">= 2.1.2 < 3"
570 | }
571 | },
572 | "ignore-by-default": {
573 | "version": "1.0.1",
574 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
575 | "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
576 | },
577 | "import-lazy": {
578 | "version": "2.1.0",
579 | "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
580 | "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
581 | },
582 | "imurmurhash": {
583 | "version": "0.1.4",
584 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
585 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
586 | },
587 | "inherits": {
588 | "version": "2.0.3",
589 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
590 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
591 | },
592 | "ini": {
593 | "version": "1.3.5",
594 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
595 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
596 | },
597 | "ipaddr.js": {
598 | "version": "1.9.1",
599 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
600 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
601 | },
602 | "is-binary-path": {
603 | "version": "2.1.0",
604 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
605 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
606 | "requires": {
607 | "binary-extensions": "^2.0.0"
608 | }
609 | },
610 | "is-ci": {
611 | "version": "2.0.0",
612 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
613 | "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
614 | "requires": {
615 | "ci-info": "^2.0.0"
616 | }
617 | },
618 | "is-extglob": {
619 | "version": "2.1.1",
620 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
621 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
622 | },
623 | "is-fullwidth-code-point": {
624 | "version": "2.0.0",
625 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
626 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
627 | },
628 | "is-glob": {
629 | "version": "4.0.1",
630 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
631 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
632 | "requires": {
633 | "is-extglob": "^2.1.1"
634 | }
635 | },
636 | "is-installed-globally": {
637 | "version": "0.3.2",
638 | "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz",
639 | "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==",
640 | "requires": {
641 | "global-dirs": "^2.0.1",
642 | "is-path-inside": "^3.0.1"
643 | }
644 | },
645 | "is-npm": {
646 | "version": "4.0.0",
647 | "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz",
648 | "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig=="
649 | },
650 | "is-number": {
651 | "version": "7.0.0",
652 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
653 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
654 | },
655 | "is-obj": {
656 | "version": "2.0.0",
657 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
658 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
659 | },
660 | "is-path-inside": {
661 | "version": "3.0.2",
662 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz",
663 | "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg=="
664 | },
665 | "is-typedarray": {
666 | "version": "1.0.0",
667 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
668 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
669 | },
670 | "is-yarn-global": {
671 | "version": "0.3.0",
672 | "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
673 | "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw=="
674 | },
675 | "json-buffer": {
676 | "version": "3.0.0",
677 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
678 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg="
679 | },
680 | "keyv": {
681 | "version": "3.1.0",
682 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
683 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
684 | "requires": {
685 | "json-buffer": "3.0.0"
686 | }
687 | },
688 | "latest-version": {
689 | "version": "5.1.0",
690 | "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
691 | "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
692 | "requires": {
693 | "package-json": "^6.3.0"
694 | }
695 | },
696 | "lowercase-keys": {
697 | "version": "1.0.1",
698 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
699 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
700 | },
701 | "make-dir": {
702 | "version": "3.1.0",
703 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
704 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
705 | "requires": {
706 | "semver": "^6.0.0"
707 | },
708 | "dependencies": {
709 | "semver": {
710 | "version": "6.3.0",
711 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
712 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
713 | }
714 | }
715 | },
716 | "media-typer": {
717 | "version": "0.3.0",
718 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
719 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
720 | },
721 | "merge-descriptors": {
722 | "version": "1.0.1",
723 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
724 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
725 | },
726 | "methods": {
727 | "version": "1.1.2",
728 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
729 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
730 | },
731 | "mime": {
732 | "version": "1.6.0",
733 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
734 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
735 | },
736 | "mime-db": {
737 | "version": "1.44.0",
738 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
739 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
740 | },
741 | "mime-types": {
742 | "version": "2.1.27",
743 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
744 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
745 | "requires": {
746 | "mime-db": "1.44.0"
747 | }
748 | },
749 | "mimic-response": {
750 | "version": "1.0.1",
751 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
752 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
753 | },
754 | "minimatch": {
755 | "version": "3.0.4",
756 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
757 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
758 | "requires": {
759 | "brace-expansion": "^1.1.7"
760 | }
761 | },
762 | "minimist": {
763 | "version": "1.2.5",
764 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
765 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
766 | },
767 | "morgan": {
768 | "version": "1.10.0",
769 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
770 | "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==",
771 | "requires": {
772 | "basic-auth": "~2.0.1",
773 | "debug": "2.6.9",
774 | "depd": "~2.0.0",
775 | "on-finished": "~2.3.0",
776 | "on-headers": "~1.0.2"
777 | },
778 | "dependencies": {
779 | "depd": {
780 | "version": "2.0.0",
781 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
782 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
783 | }
784 | }
785 | },
786 | "ms": {
787 | "version": "2.0.0",
788 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
789 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
790 | },
791 | "negotiator": {
792 | "version": "0.6.2",
793 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
794 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
795 | },
796 | "nodemon": {
797 | "version": "2.0.4",
798 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz",
799 | "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==",
800 | "requires": {
801 | "chokidar": "^3.2.2",
802 | "debug": "^3.2.6",
803 | "ignore-by-default": "^1.0.1",
804 | "minimatch": "^3.0.4",
805 | "pstree.remy": "^1.1.7",
806 | "semver": "^5.7.1",
807 | "supports-color": "^5.5.0",
808 | "touch": "^3.1.0",
809 | "undefsafe": "^2.0.2",
810 | "update-notifier": "^4.0.0"
811 | },
812 | "dependencies": {
813 | "debug": {
814 | "version": "3.2.6",
815 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
816 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
817 | "requires": {
818 | "ms": "^2.1.1"
819 | }
820 | },
821 | "ms": {
822 | "version": "2.1.2",
823 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
824 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
825 | }
826 | }
827 | },
828 | "nopt": {
829 | "version": "1.0.10",
830 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
831 | "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
832 | "requires": {
833 | "abbrev": "1"
834 | }
835 | },
836 | "normalize-path": {
837 | "version": "3.0.0",
838 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
839 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
840 | },
841 | "normalize-url": {
842 | "version": "4.5.0",
843 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
844 | "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ=="
845 | },
846 | "object-assign": {
847 | "version": "4.1.1",
848 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
849 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
850 | },
851 | "on-finished": {
852 | "version": "2.3.0",
853 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
854 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
855 | "requires": {
856 | "ee-first": "1.1.1"
857 | }
858 | },
859 | "on-headers": {
860 | "version": "1.0.2",
861 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
862 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
863 | },
864 | "once": {
865 | "version": "1.4.0",
866 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
867 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
868 | "requires": {
869 | "wrappy": "1"
870 | }
871 | },
872 | "p-cancelable": {
873 | "version": "1.1.0",
874 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
875 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw=="
876 | },
877 | "package-json": {
878 | "version": "6.5.0",
879 | "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
880 | "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
881 | "requires": {
882 | "got": "^9.6.0",
883 | "registry-auth-token": "^4.0.0",
884 | "registry-url": "^5.0.0",
885 | "semver": "^6.2.0"
886 | },
887 | "dependencies": {
888 | "semver": {
889 | "version": "6.3.0",
890 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
891 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
892 | }
893 | }
894 | },
895 | "packet-reader": {
896 | "version": "1.0.0",
897 | "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
898 | "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
899 | },
900 | "parseurl": {
901 | "version": "1.3.3",
902 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
903 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
904 | },
905 | "path-to-regexp": {
906 | "version": "0.1.7",
907 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
908 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
909 | },
910 | "pg": {
911 | "version": "8.2.1",
912 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.2.1.tgz",
913 | "integrity": "sha512-DKzffhpkWRr9jx7vKxA+ur79KG+SKw+PdjMb1IRhMiKI9zqYUGczwFprqy+5Veh/DCcFs1Y6V8lRLN5I1DlleQ==",
914 | "requires": {
915 | "buffer-writer": "2.0.0",
916 | "packet-reader": "1.0.0",
917 | "pg-connection-string": "^2.2.3",
918 | "pg-pool": "^3.2.1",
919 | "pg-protocol": "^1.2.4",
920 | "pg-types": "^2.1.0",
921 | "pgpass": "1.x",
922 | "semver": "4.3.2"
923 | },
924 | "dependencies": {
925 | "semver": {
926 | "version": "4.3.2",
927 | "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
928 | "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
929 | }
930 | }
931 | },
932 | "pg-connection-string": {
933 | "version": "2.2.3",
934 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.2.3.tgz",
935 | "integrity": "sha512-I/KCSQGmOrZx6sMHXkOs2MjddrYcqpza3Dtsy0AjIgBr/bZiPJRK9WhABXN1Uy1UDazRbi9gZEzO2sAhL5EqiQ=="
936 | },
937 | "pg-int8": {
938 | "version": "1.0.1",
939 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
940 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
941 | },
942 | "pg-pool": {
943 | "version": "3.2.1",
944 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz",
945 | "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA=="
946 | },
947 | "pg-protocol": {
948 | "version": "1.2.4",
949 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.4.tgz",
950 | "integrity": "sha512-/8L/G+vW/VhWjTGXpGh8XVkXOFx1ZDY+Yuz//Ab8CfjInzFkreI+fDG3WjCeSra7fIZwAFxzbGptNbm8xSXenw=="
951 | },
952 | "pg-types": {
953 | "version": "2.2.0",
954 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
955 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
956 | "requires": {
957 | "pg-int8": "1.0.1",
958 | "postgres-array": "~2.0.0",
959 | "postgres-bytea": "~1.0.0",
960 | "postgres-date": "~1.0.4",
961 | "postgres-interval": "^1.1.0"
962 | }
963 | },
964 | "pgpass": {
965 | "version": "1.0.2",
966 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz",
967 | "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=",
968 | "requires": {
969 | "split": "^1.0.0"
970 | }
971 | },
972 | "picomatch": {
973 | "version": "2.2.2",
974 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
975 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
976 | },
977 | "postgres-array": {
978 | "version": "2.0.0",
979 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
980 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
981 | },
982 | "postgres-bytea": {
983 | "version": "1.0.0",
984 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
985 | "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
986 | },
987 | "postgres-date": {
988 | "version": "1.0.5",
989 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz",
990 | "integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA=="
991 | },
992 | "postgres-interval": {
993 | "version": "1.2.0",
994 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
995 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
996 | "requires": {
997 | "xtend": "^4.0.0"
998 | }
999 | },
1000 | "prepend-http": {
1001 | "version": "2.0.0",
1002 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
1003 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
1004 | },
1005 | "proxy-addr": {
1006 | "version": "2.0.6",
1007 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
1008 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
1009 | "requires": {
1010 | "forwarded": "~0.1.2",
1011 | "ipaddr.js": "1.9.1"
1012 | }
1013 | },
1014 | "pstree.remy": {
1015 | "version": "1.1.8",
1016 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
1017 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
1018 | },
1019 | "pump": {
1020 | "version": "3.0.0",
1021 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
1022 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
1023 | "requires": {
1024 | "end-of-stream": "^1.1.0",
1025 | "once": "^1.3.1"
1026 | }
1027 | },
1028 | "pupa": {
1029 | "version": "2.0.1",
1030 | "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz",
1031 | "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==",
1032 | "requires": {
1033 | "escape-goat": "^2.0.0"
1034 | }
1035 | },
1036 | "qs": {
1037 | "version": "6.7.0",
1038 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
1039 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
1040 | },
1041 | "range-parser": {
1042 | "version": "1.2.1",
1043 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1044 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
1045 | },
1046 | "raw-body": {
1047 | "version": "2.4.0",
1048 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
1049 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
1050 | "requires": {
1051 | "bytes": "3.1.0",
1052 | "http-errors": "1.7.2",
1053 | "iconv-lite": "0.4.24",
1054 | "unpipe": "1.0.0"
1055 | }
1056 | },
1057 | "rc": {
1058 | "version": "1.2.8",
1059 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
1060 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
1061 | "requires": {
1062 | "deep-extend": "^0.6.0",
1063 | "ini": "~1.3.0",
1064 | "minimist": "^1.2.0",
1065 | "strip-json-comments": "~2.0.1"
1066 | }
1067 | },
1068 | "readdirp": {
1069 | "version": "3.4.0",
1070 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
1071 | "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
1072 | "requires": {
1073 | "picomatch": "^2.2.1"
1074 | }
1075 | },
1076 | "registry-auth-token": {
1077 | "version": "4.1.1",
1078 | "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz",
1079 | "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==",
1080 | "requires": {
1081 | "rc": "^1.2.8"
1082 | }
1083 | },
1084 | "registry-url": {
1085 | "version": "5.1.0",
1086 | "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz",
1087 | "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==",
1088 | "requires": {
1089 | "rc": "^1.2.8"
1090 | }
1091 | },
1092 | "responselike": {
1093 | "version": "1.0.2",
1094 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
1095 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
1096 | "requires": {
1097 | "lowercase-keys": "^1.0.0"
1098 | }
1099 | },
1100 | "safe-buffer": {
1101 | "version": "5.1.2",
1102 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1103 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
1104 | },
1105 | "safer-buffer": {
1106 | "version": "2.1.2",
1107 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1108 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1109 | },
1110 | "semver": {
1111 | "version": "5.7.1",
1112 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
1113 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
1114 | },
1115 | "semver-diff": {
1116 | "version": "3.1.1",
1117 | "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
1118 | "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
1119 | "requires": {
1120 | "semver": "^6.3.0"
1121 | },
1122 | "dependencies": {
1123 | "semver": {
1124 | "version": "6.3.0",
1125 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
1126 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
1127 | }
1128 | }
1129 | },
1130 | "send": {
1131 | "version": "0.17.1",
1132 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
1133 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
1134 | "requires": {
1135 | "debug": "2.6.9",
1136 | "depd": "~1.1.2",
1137 | "destroy": "~1.0.4",
1138 | "encodeurl": "~1.0.2",
1139 | "escape-html": "~1.0.3",
1140 | "etag": "~1.8.1",
1141 | "fresh": "0.5.2",
1142 | "http-errors": "~1.7.2",
1143 | "mime": "1.6.0",
1144 | "ms": "2.1.1",
1145 | "on-finished": "~2.3.0",
1146 | "range-parser": "~1.2.1",
1147 | "statuses": "~1.5.0"
1148 | },
1149 | "dependencies": {
1150 | "ms": {
1151 | "version": "2.1.1",
1152 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
1153 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
1154 | }
1155 | }
1156 | },
1157 | "serve-static": {
1158 | "version": "1.14.1",
1159 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
1160 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
1161 | "requires": {
1162 | "encodeurl": "~1.0.2",
1163 | "escape-html": "~1.0.3",
1164 | "parseurl": "~1.3.3",
1165 | "send": "0.17.1"
1166 | }
1167 | },
1168 | "setprototypeof": {
1169 | "version": "1.1.1",
1170 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
1171 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
1172 | },
1173 | "signal-exit": {
1174 | "version": "3.0.3",
1175 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
1176 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
1177 | },
1178 | "split": {
1179 | "version": "1.0.1",
1180 | "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
1181 | "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
1182 | "requires": {
1183 | "through": "2"
1184 | }
1185 | },
1186 | "statuses": {
1187 | "version": "1.5.0",
1188 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
1189 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
1190 | },
1191 | "string-width": {
1192 | "version": "4.2.0",
1193 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
1194 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
1195 | "requires": {
1196 | "emoji-regex": "^8.0.0",
1197 | "is-fullwidth-code-point": "^3.0.0",
1198 | "strip-ansi": "^6.0.0"
1199 | },
1200 | "dependencies": {
1201 | "ansi-regex": {
1202 | "version": "5.0.0",
1203 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
1204 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
1205 | },
1206 | "emoji-regex": {
1207 | "version": "8.0.0",
1208 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1209 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
1210 | },
1211 | "is-fullwidth-code-point": {
1212 | "version": "3.0.0",
1213 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
1214 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
1215 | },
1216 | "strip-ansi": {
1217 | "version": "6.0.0",
1218 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
1219 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
1220 | "requires": {
1221 | "ansi-regex": "^5.0.0"
1222 | }
1223 | }
1224 | }
1225 | },
1226 | "strip-ansi": {
1227 | "version": "5.2.0",
1228 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
1229 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
1230 | "requires": {
1231 | "ansi-regex": "^4.1.0"
1232 | }
1233 | },
1234 | "strip-json-comments": {
1235 | "version": "2.0.1",
1236 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
1237 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
1238 | },
1239 | "supports-color": {
1240 | "version": "5.5.0",
1241 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
1242 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
1243 | "requires": {
1244 | "has-flag": "^3.0.0"
1245 | }
1246 | },
1247 | "term-size": {
1248 | "version": "2.2.0",
1249 | "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz",
1250 | "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw=="
1251 | },
1252 | "through": {
1253 | "version": "2.3.8",
1254 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
1255 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
1256 | },
1257 | "to-readable-stream": {
1258 | "version": "1.0.0",
1259 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
1260 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q=="
1261 | },
1262 | "to-regex-range": {
1263 | "version": "5.0.1",
1264 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1265 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1266 | "requires": {
1267 | "is-number": "^7.0.0"
1268 | }
1269 | },
1270 | "toidentifier": {
1271 | "version": "1.0.0",
1272 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
1273 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
1274 | },
1275 | "touch": {
1276 | "version": "3.1.0",
1277 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
1278 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
1279 | "requires": {
1280 | "nopt": "~1.0.10"
1281 | }
1282 | },
1283 | "type-fest": {
1284 | "version": "0.8.1",
1285 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
1286 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
1287 | },
1288 | "type-is": {
1289 | "version": "1.6.18",
1290 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1291 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1292 | "requires": {
1293 | "media-typer": "0.3.0",
1294 | "mime-types": "~2.1.24"
1295 | }
1296 | },
1297 | "typedarray-to-buffer": {
1298 | "version": "3.1.5",
1299 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
1300 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
1301 | "requires": {
1302 | "is-typedarray": "^1.0.0"
1303 | }
1304 | },
1305 | "undefsafe": {
1306 | "version": "2.0.3",
1307 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
1308 | "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==",
1309 | "requires": {
1310 | "debug": "^2.2.0"
1311 | }
1312 | },
1313 | "unique-string": {
1314 | "version": "2.0.0",
1315 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
1316 | "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
1317 | "requires": {
1318 | "crypto-random-string": "^2.0.0"
1319 | }
1320 | },
1321 | "unpipe": {
1322 | "version": "1.0.0",
1323 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1324 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
1325 | },
1326 | "update-notifier": {
1327 | "version": "4.1.0",
1328 | "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz",
1329 | "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==",
1330 | "requires": {
1331 | "boxen": "^4.2.0",
1332 | "chalk": "^3.0.0",
1333 | "configstore": "^5.0.1",
1334 | "has-yarn": "^2.1.0",
1335 | "import-lazy": "^2.1.0",
1336 | "is-ci": "^2.0.0",
1337 | "is-installed-globally": "^0.3.1",
1338 | "is-npm": "^4.0.0",
1339 | "is-yarn-global": "^0.3.0",
1340 | "latest-version": "^5.0.0",
1341 | "pupa": "^2.0.1",
1342 | "semver-diff": "^3.1.1",
1343 | "xdg-basedir": "^4.0.0"
1344 | }
1345 | },
1346 | "url-parse-lax": {
1347 | "version": "3.0.0",
1348 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
1349 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
1350 | "requires": {
1351 | "prepend-http": "^2.0.0"
1352 | }
1353 | },
1354 | "utils-merge": {
1355 | "version": "1.0.1",
1356 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1357 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
1358 | },
1359 | "vary": {
1360 | "version": "1.1.2",
1361 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1362 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
1363 | },
1364 | "widest-line": {
1365 | "version": "3.1.0",
1366 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
1367 | "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
1368 | "requires": {
1369 | "string-width": "^4.0.0"
1370 | }
1371 | },
1372 | "wrappy": {
1373 | "version": "1.0.2",
1374 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1375 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
1376 | },
1377 | "write-file-atomic": {
1378 | "version": "3.0.3",
1379 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
1380 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
1381 | "requires": {
1382 | "imurmurhash": "^0.1.4",
1383 | "is-typedarray": "^1.0.0",
1384 | "signal-exit": "^3.0.2",
1385 | "typedarray-to-buffer": "^3.1.5"
1386 | }
1387 | },
1388 | "xdg-basedir": {
1389 | "version": "4.0.0",
1390 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
1391 | "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q=="
1392 | },
1393 | "xtend": {
1394 | "version": "4.0.2",
1395 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
1396 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
1397 | }
1398 | }
1399 | }
1400 |
--------------------------------------------------------------------------------