Add Server Side Rendering

This commit is contained in:
Amit Jakubowicz 2019-07-19 18:00:51 +02:00
parent 5a38dfce08
commit 231c6a9333
24 changed files with 372 additions and 112 deletions

6
@types/graphql.d.ts vendored
View file

@ -0,0 +1,6 @@
// tslint:disable
// graphql typescript definitions
// tslint:enable

3
@types/index.d.ts vendored
View file

@ -1,7 +1,6 @@
export type EventStatus = 'confirmed' | 'canceled'
// tslint:disable
// graphql typescript definitions
declare namespace GQL {
interface IGraphQLResponseRoot {
data?: IQuery | IMutation;
@ -95,7 +94,6 @@ declare namespace GQL {
event: ICalendarEvent;
start: string;
end: string;
timeZone: string;
}
interface IEventMeta {
@ -215,5 +213,4 @@ declare namespace GQL {
status?: string | null;
}
}
// tslint:enable

View file

@ -1,9 +1,5 @@
import * as React from "react"
import {
Redirect,
Route,
Switch,
} from "react-router-dom"
import { Redirect, Route, Switch } from "react-router-dom"
import Calendar from "../Calendar/Calendar"
import CreateEvent from "../Event/CreateEvent"
import EditEvent from "../Event/EditEvent"
@ -16,21 +12,35 @@ import InitializeSession from "./Auth/InitializeSession"
import Signup from "./Auth/Signup"
import Signout from "./Auth/Signout"
import OccurrenceDetails from "./Occurrence/OccurrenceDetails"
import { Global, css } from "@emotion/core"
const App = () => (
<Root>
<Global
styles={css`
body {
margin: 0;
height: 100vh;
}
#app {
height: 100%;
}
`}
/>
<StyledHeader />
<Content>
<Switch>
<Route path="/create" component={CreateEvent} />
<Route
path="/event/:eventId/edit"
render={(
routeProps: RouteComponentProps<{ eventId: string }>
) => <EditEvent eventId={routeProps.match.params.eventId} />}
render={(routeProps: RouteComponentProps<{ eventId: string }>) => (
<EditEvent eventId={routeProps.match.params.eventId} />
)}
/>
<Route
path="/o/:sanitizedEventName/:occurrenceId"
component={OccurrenceDetails}
/>
<Route path="/o/:sanitizedEventName/:occurrenceId" component={OccurrenceDetails}/>
<Route path="/init-session/:hash" component={InitializeSession} />
<Route path="/login" component={Login} />
<Route path="/signup" component={Signup} />
@ -59,9 +69,9 @@ const Content = styled.div`
`
const StyledFooter = styled(Footer)`
grid-row: footer
grid-row: footer;
`
const StyledHeader = styled(Header)`
grid-row: header
grid-row: header;
`
export default App

View file

@ -21,7 +21,7 @@ const InitializeSession = (props: Props) => {
setResponseCode(res.status)
setLoading(false)
if (res.status === 200) {
// props.history.replace("/my-events")
props.history.replace("/my-events")
}
})
})
@ -32,7 +32,7 @@ const InitializeSession = (props: Props) => {
{loading
? "Loading..."
: responseCode === 200
? "You will be redirected now"
? "You will be redirected now"
: "Validation failed. Please try to log in again."}
</Root>
)

View file

@ -12,16 +12,15 @@ const Signup = () => {
<form
onSubmit={(e: FormEvent) => {
e.preventDefault()
const data = new FormData(e.target as HTMLFormElement)
const form = e.target as any
fetch("/api/signup", {
method: "post",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({
name: data.get("name"),
email: data.get("email")
name: form.name.value,
email: form.email.value
})
}).then((res) => {
if (res.status === 200) {

View file

@ -9,13 +9,15 @@ const { Provider, Consumer } = React.createContext<IAppContext>({ me: null })
const AppContextProvider = props => (
<MeQuery>
{({ data, loading, error }) => (
<Provider value={data}>
{
props.children
}
</Provider>
)}
{({ data, loading, error }) => {
return (
<Provider value={data}>
{
props.children
}
</Provider>
)
}}
</MeQuery>
)

View file

@ -17,6 +17,9 @@ const OccurrenceDetails = (props: Props) => {
if (loading) {
return <p>loading...</p>
}
if (error) {
return <p>{error.message}</p>
}
return (
<div>
{ data.occurrence.event.info[0].title}

View file

@ -7,7 +7,6 @@ const query = gql`
id
start
end
timeZone
event {
id
owner {
@ -29,7 +28,6 @@ export interface OccurrenceDetailsData {
id: string
start: string
end: string
timeZone: string
event: {
owner: {
id: string

View file

@ -1,26 +1,27 @@
import * as React from 'react'
import {AppContextProvider} from "./Context/AppContext"
import {BrowserRouter as Router, Redirect, Route, Switch} from "react-router-dom"
import {BrowserRouter as Router} from "react-router-dom"
import {ApolloProvider} from "react-apollo"
import {HttpLink} from "apollo-link-http"
import {ApolloClient} from "apollo-client"
import {InMemoryCache} from "apollo-cache-inmemory"
import fetch from 'node-fetch'
interface Props {
children: React.ReactChild | React.ReactChildren
}
const httpLink = new HttpLink({
uri: "/graphql"
uri: "/graphql",
fetch
})
const graphqlClient = new ApolloClient({
connectToDevTools: true,
link: httpLink,
cache: new InMemoryCache()
cache: new InMemoryCache().restore(window.__APOLLO_DATA__)
}) as ApolloClient<any>
const Providers = (props: Props) => (
<ApolloProvider client={graphqlClient}>
<AppContextProvider>

View file

@ -2,30 +2,12 @@ import * as React from "react"
import * as ReactDOM from "react-dom"
import App from "./App"
import Providers from "./Providers"
import css from '@emotion/css'
import css from "@emotion/css"
const appWrapper = document.createElement("div")
appWrapper.id = 'appcontainer'
document.body.appendChild(appWrapper)
ReactDOM.render(
const container = document.getElementById("app")
ReactDOM.hydrate(
<Providers>
<App />
</Providers>,
appWrapper
container
)
const styled = css`
body {
margin: 0;
height: 100vh;
}
#appcontainer {
height: 100%;
}
`
const styleElem = document.createElement('style')
styleElem.innerText = styled.styles;
document.body.appendChild(styleElem)
export default App

View file

@ -22,29 +22,32 @@ const endOfThisMonth = (
)()
const Calendar = (props: Props) => (
<OccurrencesQuery
variables={{
filter: {
from: beginningOfThisMonth,
to: endOfThisMonth
}
}}
>
{({data, error, loading}) => {
if (loading) {
return "I am a Spinner"
}
if (error) {
return error.message
}
const Calendar = (props: Props) => {
return (
<OccurrencesQuery
variables={{
filter: {
from: "2019-06-01",
to: "2019-06-30"
}
}}
>
{({data, error, loading}) => {
if (loading) {
return "I am a Spinner"
}
if (error) {
return error.message
}
if (!data.occurrences.length) {
return <p>No occurrences</p>
}
return <List occurrences={data.occurrences}/>
}}
</OccurrencesQuery>
)
if (!data.occurrences.length) {
return <p>No occurrences</p>
}
return <List occurrences={data.occurrences}/>
}}
</OccurrencesQuery>
)
}
export default Calendar

View file

@ -2,13 +2,13 @@ import * as React from "react"
import { OccurrenceData } from "../../Event/OccurrencesQuery"
import { AppContext } from "../../App/Context/AppContext"
import { Link } from 'react-router-dom'
import styled from '@emotion/styled'
interface Props {
occurrence: OccurrenceData
}
const sanitizeEventName = (name: string) => {
encodeURIComponent
return encodeURIComponent(name.trim().toLocaleLowerCase()
.replace(/\s+/g,'-'))
@ -29,7 +29,7 @@ const ListItem = (props: Props) => {
</Link>
{
me && me.events.find(myEvent => myEvent.id === event.id) ? (
<Link to={`/event/${event.id}/edit`}>Edit</Link>
<EditLink to={`/event/${event.id}/edit`}>Edit</EditLink>
) : null
}
</div>
@ -38,4 +38,9 @@ const ListItem = (props: Props) => {
)
}
const EditLink = styled(Link)`
margin-left: 8px;
font-size: 0.6em;
`
export default ListItem

View file

@ -0,0 +1,25 @@
import * as React from 'react'
import {AppContextProvider} from "../App/Context/AppContext"
import {ApolloProvider} from "react-apollo"
import {ApolloClient} from "apollo-client"
import {InMemoryCache} from "apollo-cache-inmemory"
import { StaticRouter } from 'react-router'
interface Props {
children: React.ReactChild | React.ReactChildren
graphqlClient: ApolloClient<InMemoryCache>
location: string
}
const SSRProviders = (props: Props) => (
<ApolloProvider client={props.graphqlClient}>
<AppContextProvider>
<StaticRouter location={props.location}>
{ props.children }
</StaticRouter>
</AppContextProvider>
</ApolloProvider>
)
export default SSRProviders

57
client/SSR/handler.tsx Normal file
View file

@ -0,0 +1,57 @@
import { Request, Response } from "express-serve-static-core"
import * as ReactDOMServer from "react-dom/server"
import { renderStylesToString } from "emotion-server"
import App from "../App/App"
import * as React from "react"
import SSRProviders from "./SSRProviders"
import * as fs from "fs"
import * as path from "path"
import * as Mustache from "mustache"
import { ApolloClient } from "apollo-client"
import { InMemoryCache } from "apollo-cache-inmemory"
import { HttpLink } from "apollo-link-http"
import fetch from "node-fetch"
import { getDataFromTree } from "react-apollo"
import apolloLogger from "apollo-link-logger"
import { ApolloLink } from "apollo-link"
export const httpSSRHandler = async (req: Request, res: Response) => {
res.status(200)
const httpLink = new HttpLink({
uri: "http://localhost:4000/graphql",
fetch,
headers: {
cookie: req.header("Cookie")
}
})
const link = ApolloLink.from([apolloLogger, httpLink])
const graphqlClient = new ApolloClient({
connectToDevTools: true,
link,
cache: new InMemoryCache(),
ssrMode: true,
}) as ApolloClient<any>
const app = (
<SSRProviders location={req.path} graphqlClient={graphqlClient}>
<App />
</SSRProviders>
)
const appWithData = await getDataFromTree(app)
const appBody = renderStylesToString(appWithData)
const initialState = graphqlClient.extract()
const template = fs.readFileSync(
path.join(__dirname, "./index.html.mustache"),
"utf-8"
)
const result = Mustache.render(template, {
appBody,
apolloData: JSON.stringify(initialState)
})
res.send(result)
}

View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Quepasa Alpujarra</title>
<script type="application/javascript">
__APOLLO_DATA__ = {{{ apolloData }}};
</script>
</head>
<body>
<div id="app">{{{ appBody }}}</div>
<script type="application/javascript" src="/bundle.js"></script>
</body>
</html>

8
client/SSR/index.tsx Normal file
View file

@ -0,0 +1,8 @@
import * as React from 'react'
import * as express from 'express'
import { httpSSRHandler } from './handler'
const app = express()
app.get('/*', httpSSRHandler)
app.listen(5000)
console.log('alrigh')

View file

@ -1,19 +1,25 @@
{
"name": "cc-web-client",
"version": "1.0.0",
"name": "client",
"version": "0.0.1",
"main": "index.ts",
"license": "private",
"private": true,
"scripts": {
"start": "NODE_ENV=development webpack-dev-server --config ./webpack.config.ts --hot --progress"
"start": "NODE_ENV=development webpack-dev-server --config ./webpack.config.ts --hot --progress",
"ssr": "ts-node SSR/index.tsx"
},
"dependencies": {
"@emotion/styled": "^10.0.12",
"@types/mustache": "^0.8.32",
"@types/react-router-dom": "^4.3.3",
"apollo-cache-inmemory": "^1.3.8",
"apollo-client": "^2.4.5",
"apollo-link": "^1.2.12",
"apollo-link-http": "^1.5.14",
"apollo-link-logger": "^1.2.3",
"date-fns": "^1.29.0",
"emotion-server": "^10.0.14",
"express": "^4.17.1",
"formik": "^1.4.1",
"graphql": "^14.0.2",
"graphql-tag": "^2.9.2",
@ -21,6 +27,9 @@
"jest": "^24.1.0",
"jest-cli": "24.1.0",
"keycode": "^2.2.0",
"mustache": "^3.0.1",
"node-fetch": "^2.6.0",
"nodemon": "^1.19.1",
"ramda": "^0.26.1",
"react": "^16.8.6",
"react-apollo": "^2.2.4",
@ -44,6 +53,7 @@
"@types/jest": "^24.0.6",
"@types/node": "^11.9.4",
"@types/react": "^16.4.18",
"@types/react-dom": "^16.8.4",
"@types/react-loadable": "^5.4.1",
"@types/react-router": "^4.0.31",
"@types/styled-components": "^4.1.10",

View file

@ -1,6 +1,9 @@
import * as webpack from 'webpack'
import * as path from "path"
import * as HtmlWebpackPlugin from 'html-webpack-plugin'
import * as express from 'express'
import * as WebpackDevServer from "webpack-dev-server"
import {httpSSRHandler} from "./SSR/handler"
const config: webpack.Configuration = {
entry: './App/index.tsx',
@ -10,6 +13,10 @@ const config: webpack.Configuration = {
devServer: {
historyApiFallback: true,
hot: true,
before: (app: express.Application, server: WebpackDevServer) => {
//todo: improve the regex
app.get(/^((?!\.\w+).)*$/, httpSSRHandler)
},
proxy: {
'/graphql': {
redirect: false,

View file

@ -16,6 +16,7 @@
],
"scripts": {
"codegen": "gql2ts ./schema.graphql -o ./@types/graphql.d.ts",
"ssr": "(cd client; yarn ssr)",
"server": "(cd server; yarn start)",
"client": "(cd client; yarn start)"
},

View file

@ -54,7 +54,6 @@ type EventOccurrence {
event: CalendarEvent!
start: String!
end: String!
timeZone: String!
}
type Location {

View file

@ -1,9 +1,7 @@
{
"type": "postgres",
"host": "localhost",
"database": "qpa",
"username": "qpa",
"password": "qpa",
"database": "qpa-dev",
"entities": ["src/**/*.entity.ts"],
"migrations": ["migrations/*.ts"],
"cli": {

View file

@ -12,6 +12,7 @@
"apollo-server": "^2.4.8",
"apollo-server-testing": "^2.4.8",
"atob": "^2.1.2",
"client": "0.0.1",
"axios": "^0.18.0",
"cookie": "^0.3.1",
"cors": "^2.8.4",
@ -32,6 +33,7 @@
"pg": "^7.8.2",
"random-string": "^0.2.0",
"randomstring": "^1.1.5",
"react-dom": "^16.8.6",
"rrule": "^2.6.0",
"superagent": "^3.8.3",
"typeorm": "^0.2.14",
@ -61,7 +63,9 @@
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testMatch": ["**/*.spec.ts"],
"testMatch": [
"**/*.spec.ts"
],
"moduleFileExtensions": [
"ts",
"tsx",

View file

@ -159,7 +159,4 @@ export class EventOccurrence extends BaseEntity {
@Column()
end: string
@Column({nullable: true})
timeZone: string
}

174
yarn.lock
View file

@ -971,6 +971,11 @@
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.1.tgz#8529b7412a6eb4b48bdf6e720cc1b8e6e1e17628"
integrity sha512-8M3VN0hetwhsJ8dH8VkVy7xo5/1VoBsDOk/T4SJOeXwTO1c4uIqVNx2qyecLFnnUWD5vvUqHQ1gASSeUN6zcTg==
"@emotion/utils@0.11.2":
version "0.11.2"
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.2.tgz#713056bfdffb396b0a14f1c8f18e7b4d0d200183"
integrity sha512-UHX2XklLl3sIaP6oiMmlVzT0J+2ATTVpf0dHQVyPJHTkOITvXfaSqnRk6mdDhV9pR8T/tHc3cex78IKXssmzrA==
"@emotion/weak-memoize@0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.2.tgz#63985d3d8b02530e0869962f4da09142ee8e200e"
@ -1497,30 +1502,25 @@
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*", "@types/node@^11.11.0":
"@types/mustache@^0.8.32":
version "0.8.32"
resolved "https://registry.yarnpkg.com/@types/mustache/-/mustache-0.8.32.tgz#7db3b81f2bf450bd38805f596d20eca97c4ed595"
integrity sha512-RTVWV485OOf4+nO2+feurk0chzHkSjkjALiejpHltyuMf/13fGymbbNNFrSKdSSUg1TIwzszXdWsVirxgqYiFA==
"@types/node@*", "@types/node@>=6", "@types/node@^11.11.0", "@types/node@^11.9.4":
version "11.11.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.0.tgz#070e9ce7c90e727aca0e0c14e470f9a93ffe9390"
integrity sha512-D5Rt+HXgEywr3RQJcGlZUCTCx1qVbCZpVk3/tOOA6spLNZdGm8BU+zRgdRYDoF1pO3RuXLxADzMrF903JlQXqg==
"@types/node@>=6":
version "12.0.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.4.tgz#46832183115c904410c275e34cf9403992999c32"
integrity sha512-j8YL2C0fXq7IONwl/Ud5Kt0PeXw22zGERt+HSSnwbKOJVsAGkEz3sFCYwaF9IOuoG1HOtE0vKCj6sXF7Q0+Vaw==
"@types/node@^10.1.0":
version "10.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9"
integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw==
"@types/node@^11.9.4":
version "11.13.13"
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.13.tgz#a3d2a8a908ce322f24f0f8c88160b44c7dd5c452"
integrity sha512-GFWH7e4Q/OGLAO545bupVju+nE1YtLSwYAdLfSzAXnTPqoqKoXCOEtB7Cluvg9B/h2nGLhyzCDyCInYvrOE2nw==
version "10.14.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.12.tgz#0eec3155a46e6c4db1f27c3e588a205f767d622f"
integrity sha512-QcAKpaO6nhHLlxWBvpc4WeLrTvPqlHOvaj0s5GriKkA1zq+bsFBPpfYCvQhLqLgYlIko8A9YrPdaMHCo5mBcpg==
"@types/node@^8.0.7":
version "8.10.49"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.49.tgz#f331afc5efed0796798e5591d6e0ece636969b7b"
integrity sha512-YX30JVx0PvSmJ3Eqr74fYLGeBxD+C7vIL20ek+GGGLJeUbVYRUW3EzyAXpIRA0K8c8o0UWqR/GwEFYiFoz1T8w==
version "8.10.50"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.50.tgz#f3d68482b1f54b5f4fba8daaac385db12bb6a706"
integrity sha512-+ZbcUwJdaBgOZpwXeT0v+gHC/jQbEfzoc9s4d0rN0JIKeQbuTrT+A2n1aQY6LpZjrLXJT7avVUqiCecCJeeZxA==
"@types/prettier@1.15.2":
version "1.15.2"
@ -1537,6 +1537,13 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
"@types/react-dom@^16.8.4":
version "16.8.4"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.4.tgz#7fb7ba368857c7aa0f4e4511c4710ca2c5a12a88"
integrity sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA==
dependencies:
"@types/react" "*"
"@types/react-loadable@^5.4.1":
version "5.5.1"
resolved "https://registry.yarnpkg.com/@types/react-loadable/-/react-loadable-5.5.1.tgz#f04a262f16e9f088098ddad1aa50682ad0984aa7"
@ -2120,6 +2127,11 @@ apollo-link-http@^1.5.14:
apollo-link-http-common "^0.2.13"
tslib "^1.9.3"
apollo-link-logger@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/apollo-link-logger/-/apollo-link-logger-1.2.3.tgz#1f3e6f7849ce7a7e3aa822141fe062cfa278b1e1"
integrity sha512-GaVwdHyXmawfvBlHfZkFkBHH3+YH7wibzSCc4/YpIbPVtbtZqi0Qop18w++jgpw385W083DMOdYe2eJsKkZdag==
apollo-link@^1.0.0, apollo-link@^1.2.11:
version "1.2.11"
resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.11.tgz#493293b747ad3237114ccd22e9f559e5e24a194d"
@ -2130,6 +2142,16 @@ apollo-link@^1.0.0, apollo-link@^1.2.11:
tslib "^1.9.3"
zen-observable-ts "^0.8.18"
apollo-link@^1.2.12:
version "1.2.12"
resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.12.tgz#014b514fba95f1945c38ad4c216f31bcfee68429"
integrity sha512-fsgIAXPKThyMVEMWQsUN22AoQI+J/pVXcjRGAShtk97h7D8O+SPskFinCGEkxPeQpE83uKaqafB2IyWdjN+J3Q==
dependencies:
apollo-utilities "^1.3.0"
ts-invariant "^0.4.0"
tslib "^1.9.3"
zen-observable-ts "^0.8.19"
apollo-link@^1.2.3:
version "1.2.9"
resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.9.tgz#40a8f0b90716ce3fd6beb27b7eae1108b92e0054"
@ -3024,6 +3046,11 @@ buffer-from@1.x, buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
buffer-from@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0"
integrity sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==
buffer-indexof@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
@ -3303,7 +3330,7 @@ chokidar@2.0.4:
optionalDependencies:
fsevents "^1.2.2"
chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.6:
chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.5, chokidar@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5"
integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==
@ -3785,6 +3812,16 @@ create-ecdh@^4.0.0:
bn.js "^4.1.0"
elliptic "^6.0.0"
create-emotion-server@10.0.14:
version "10.0.14"
resolved "https://registry.yarnpkg.com/create-emotion-server/-/create-emotion-server-10.0.14.tgz#51378f2f5a38d55b6da403a7f975d51b7cf221b5"
integrity sha512-wYPojM+irHtmIZuRmYeKYaJSttC3/3Cj4DI8B1JmYq8P9IQ5FZCyfahdHhI3OSrNHIkWAX1Kjt4kbbqxVbUjPw==
dependencies:
"@emotion/utils" "0.11.2"
html-tokenize "^2.0.0"
multipipe "^1.0.2"
through "^2.3.8"
create-emotion@^10.0.9:
version "10.0.9"
resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-10.0.9.tgz#290c2036126171c9566fa24f49c9241d54625138"
@ -4357,6 +4394,13 @@ dotenv@^5.0.1:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef"
integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==
duplexer2@^0.1.2:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=
dependencies:
readable-stream "^2.0.2"
duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
@ -4420,6 +4464,13 @@ emojis-list@^2.0.0:
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
emotion-server@^10.0.14:
version "10.0.14"
resolved "https://registry.yarnpkg.com/emotion-server/-/emotion-server-10.0.14.tgz#dd4146f1e827c7dcb1861bbd92e420d50167e83f"
integrity sha512-lxRyEISpiF8G7Q3Dt8xnK+flWfWeimo2PDRO8Me3zosUDJe8J2AzYe7pe80pFs3GMeOES98oV7/Ah5tiCTAGjw==
dependencies:
create-emotion-server "10.0.14"
emotion@^10.0.9:
version "10.0.9"
resolved "https://registry.yarnpkg.com/emotion/-/emotion-10.0.9.tgz#2c37598af13df31dcd35a1957eaa8830f368c066"
@ -5868,6 +5919,17 @@ html-minifier@^3.2.3:
relateurl "0.2.x"
uglify-js "3.4.x"
html-tokenize@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/html-tokenize/-/html-tokenize-2.0.0.tgz#8b3a9a5deb475cae6a6f9671600d2c20ab298251"
integrity sha1-izqaXetHXK5qb5ZxYA0sIKspglE=
dependencies:
buffer-from "~0.1.1"
inherits "~2.0.1"
minimist "~0.0.8"
readable-stream "~1.0.27-1"
through2 "~0.4.1"
html-webpack-plugin@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b"
@ -8327,7 +8389,7 @@ minimist@^1.1.1, minimist@^1.2.0:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
minimist@~0.0.1:
minimist@~0.0.1, minimist@~0.0.8:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
@ -8425,6 +8487,19 @@ multicast-dns@^6.0.1:
dns-packet "^1.3.1"
thunky "^1.0.2"
multipipe@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-1.0.2.tgz#cc13efd833c9cda99f224f868461b8e1a3fd939d"
integrity sha1-zBPv2DPJzamfIk+GhGG44aP9k50=
dependencies:
duplexer2 "^0.1.2"
object-assign "^4.1.0"
mustache@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.1.tgz#873855f23aa8a95b150fb96d9836edbc5a1d248a"
integrity sha512-jFI/4UVRsRYdUbuDTKT7KzfOp7FiD5WzYmmwNwXyUVypC0xjoTL78Fqc0jHUPIvvGD+6DQSPHIt1NE7D1ArsqA==
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
@ -8525,6 +8600,11 @@ node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.3.0:
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5"
integrity sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==
node-fetch@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-forge@0.7.5:
version "0.7.5"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df"
@ -8640,6 +8720,22 @@ nodemon@^1.18.10:
undefsafe "^2.0.2"
update-notifier "^2.5.0"
nodemon@^1.19.1:
version "1.19.1"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.1.tgz#576f0aad0f863aabf8c48517f6192ff987cd5071"
integrity sha512-/DXLzd/GhiaDXXbGId5BzxP1GlsqtMGM9zTmkWrgXtSqjKmGSbLicM/oAy4FR0YWm14jCHRwnR31AHS2dYFHrg==
dependencies:
chokidar "^2.1.5"
debug "^3.1.0"
ignore-by-default "^1.0.1"
minimatch "^3.0.4"
pstree.remy "^1.1.6"
semver "^5.5.0"
supports-color "^5.2.0"
touch "^3.1.0"
undefsafe "^2.0.2"
update-notifier "^2.5.0"
nopt@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
@ -8753,6 +8849,11 @@ object-keys@^1.0.12:
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032"
integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==
object-keys@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=
object-path@^0.11.4:
version "0.11.4"
resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949"
@ -9942,6 +10043,16 @@ readable-stream@^3.0.6:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@~1.0.17, readable-stream@~1.0.27-1:
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "0.0.1"
string_decoder "~0.10.x"
readdirp@^2.0.0, readdirp@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
@ -11249,7 +11360,15 @@ through2@^2.0.0:
readable-stream "~2.3.6"
xtend "~4.0.1"
through@2, through@^2.3.6:
through2@~0.4.1:
version "0.4.2"
resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b"
integrity sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=
dependencies:
readable-stream "~1.0.17"
xtend "~2.1.1"
through@2, through@^2.3.6, through@^2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
@ -12313,6 +12432,13 @@ xtend@^4.0.0, xtend@~4.0.1:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
xtend@~2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b"
integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os=
dependencies:
object-keys "~0.4.0"
y18n@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
@ -12461,6 +12587,14 @@ zen-observable-ts@^0.8.18:
tslib "^1.9.3"
zen-observable "^0.8.0"
zen-observable-ts@^0.8.19:
version "0.8.19"
resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.19.tgz#c094cd20e83ddb02a11144a6e2a89706946b5694"
integrity sha512-u1a2rpE13G+jSzrg3aiCqXU5tN2kw41b+cBZGmnc+30YimdkKiDj9bTowcB41eL77/17RF/h+393AuVgShyheQ==
dependencies:
tslib "^1.9.3"
zen-observable "^0.8.0"
zen-observable@^0.8.0:
version "0.8.13"
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.13.tgz#a9f1b9dbdfd2d60a08761ceac6a861427d44ae2e"