Merge in 4.0.0 (#850)

* merge in 4.0

* dev mode with firebase impl

* useReducer for toasts state
main
Michael Fix 5 years ago committed by repo-ranger[bot]
parent 54fdf2fe46
commit e0ed4bebdc

1
.gitignore vendored

@ -9,3 +9,4 @@ cypress/screenshots
packaged
coverage
public/service-worker.js
private-key.json

@ -0,0 +1,93 @@
import React from 'react'
const key = 'CARBON_CTA_1'
class Toast extends React.Component {
state = {
open: false
}
close = () => {
this.setState({ open: false })
window.localStorage.setItem(key, true)
}
componentDidMount() {
window.localStorage.removeItem('CARBON_CTA')
if (!window.localStorage.getItem(key)) {
this.setState({ open: true })
}
}
render() {
if (process.env.NODE_ENV !== 'production') {
return null
}
if (!this.state.open) {
return null
}
return (
<div className="toast mb4">
<div className="toast-content">
<p>Never lose a Carbon again - save your work automatically!</p>
Click &quot;Sign up&quot; to try it out!
<button className="close-toast" onClick={this.close}>
&times;
</button>
</div>
<style jsx>
{`
@keyframes slide {
from {
transform: translateY(-128px);
}
to {
transform: translateY(0px);
}
}
.toast {
padding: 8px 16px;
color: #fff;
border: 1px solid #fff;
border-radius: 2px;
margin-top: calc(var(--x4) * -1);
animation-name: slide;
animation-duration: 600ms;
}
.toast-content {
display: flex;
align-items: center;
}
a {
text-decoration: underline;
}
.close-toast {
padding-left: 0;
padding-right: 0;
background: transparent;
color: white;
border: none;
font-size: 100%;
margin-left: 32px;
text-decoration: none;
cursor: pointer;
}
p {
margin: 0;
margin-right: 12px;
}
`}
</style>
</div>
)
}
}
export default Toast

@ -1,4 +1,10 @@
import React from 'react'
import api from '../lib/api'
export default React.createContext(api)
const Context = React.createContext(api)
export function useAPI() {
return React.useContext(Context)
}
export default Context

@ -0,0 +1,34 @@
import React from 'react'
import firebase from '../lib/client'
// IDEA: just read from firebase store at request time?
import { client } from '../lib/api'
export const Context = React.createContext(null)
export function useAuth() {
return React.useContext(Context)
}
function AuthContext(props) {
const [user, setState] = React.useState(null)
React.useEffect(() => {
if (firebase) {
firebase.auth().onAuthStateChanged(newUser => setState(newUser))
}
}, [])
React.useEffect(() => {
if (user) {
user.getIdToken().then(jwt => {
client.defaults.headers['Authorization'] = jwt ? `Bearer ${jwt}` : undefined
})
} else {
delete client.defaults.headers['Authorization']
}
}, [user])
return <Context.Provider value={user}>{props.children}</Context.Provider>
}
export default AuthContext

@ -21,6 +21,7 @@ const Button = ({
margin = 0,
title,
Component = 'button',
display,
...props
}) => (
<Component id={id} onClick={onClick} disabled={disabled} {...props}>
@ -29,7 +30,7 @@ const Button = ({
<style jsx>
{`
${Component} {
display: flex;
display: ${display || 'flex'};
flex: ${flex};
background-color: ${background};
color: ${color};

@ -2,6 +2,8 @@
import React from 'react'
import domtoimage from 'dom-to-image'
import Dropzone from 'dropperx'
import debounce from 'lodash.debounce'
import dynamic from 'next/dynamic'
// Ours
import ApiContext from './ApiContext'
@ -14,6 +16,9 @@ import Carbon from './Carbon'
import ExportMenu from './ExportMenu'
import Themes from './Themes'
import TweetButton from './TweetButton'
import LoginButton from './LoginButton'
import FontFace from './FontFace'
import LanguageIcon from './svg/Language'
import {
LANGUAGES,
LANGUAGE_MIME_HASH,
@ -30,10 +35,13 @@ import {
} from '../lib/constants'
import { serializeState, getRouteState } from '../lib/routing'
import { getSettings, unescapeHtml, formatCode, omit } from '../lib/util'
import LanguageIcon from './svg/Language'
const languageIcon = <LanguageIcon />
const SnippetToolbar = dynamic(() => import('./SnippetToolbar'), {
loading: () => null
})
const getConfig = omit(['code'])
class Editor extends React.Component {
@ -43,6 +51,7 @@ class Editor extends React.Component {
super(props)
this.state = {
...DEFAULT_SETTINGS,
...this.props.snippet,
loading: true
}
@ -57,22 +66,13 @@ class Editor extends React.Component {
}
async componentDidMount() {
const { queryState, parameter } = getRouteState(this.props.router)
// TODO we could create an interface for loading this config, so that it looks identical
// whether config is loaded from localStorage, gist, or even something like IndexDB
let gistState
if (this.context.gist && parameter) {
const { config, ...gist } = (await this.context.gist.get(parameter)) || {}
if (typeof config === 'object') {
this.gist = gist
gistState = config
}
}
const { queryState } = getRouteState(this.props.router)
const newState = {
// TODO we could create an interface for loading this config, so that it looks identical
// whether config is loaded from localStorage, gist, or even something like IndexDB
// Load options from gist or localStorage
...(gistState ? gistState : getSettings(localStorage)),
...(this.props.snippet ? null : getSettings(localStorage)),
// and then URL params
...queryState,
loading: false
@ -87,7 +87,7 @@ class Editor extends React.Component {
newState.fontFamily = DEFAULT_SETTINGS.fontFamily
}
this.updateState(newState)
this.setState(newState)
this.isSafari =
window.navigator &&
@ -103,13 +103,11 @@ class Editor extends React.Component {
getTheme = () => this.props.themes.find(t => t.id === this.state.theme) || DEFAULT_THEME
updateState = updates => {
this.setState(updates, () => {
if (!this.gist) {
this.props.onUpdate(this.state)
}
})
}
onUpdate = debounce(updates => this.props.onUpdate(updates), 750, {
trailing: true,
leading: true
})
updateState = updates => this.setState(updates, () => this.onUpdate(this.state))
updateCode = code => this.updateState({ code })
@ -313,6 +311,28 @@ class Editor extends React.Component {
// create toast here in the future
})
handleSnippetCreate = () =>
this.context.snippet
.create(this.state)
.then(data => this.props.setSnippet(data))
.then(() =>
this.props.setToasts({
type: 'SET',
toasts: [{ children: 'Snippet duplicated!', timeout: 3000 }]
})
)
handleSnippetDelete = () =>
this.context.snippet
.delete(this.props.snippet.id)
.then(() => this.props.setSnippet(null))
.then(() =>
this.props.setToasts({
type: 'SET',
toasts: [{ children: 'Snippet deleted', timeout: 3000 }]
})
)
render() {
const {
highlights,
@ -331,6 +351,7 @@ class Editor extends React.Component {
return (
<div className="editor">
<Toolbar>
<LoginButton />
<Themes
theme={theme}
highlights={highlights}
@ -398,6 +419,13 @@ class Editor extends React.Component {
</Overlay>
)}
</Dropzone>
{this.props.snippet && (
<SnippetToolbar
snippet={this.props.snippet}
onCreate={this.handleSnippetCreate}
onDelete={this.handleSnippetDelete}
/>
)}
<FontFace {...config} />
<style jsx>
{`
@ -419,20 +447,6 @@ class Editor extends React.Component {
}
}
function FontFace(config) {
return (
<style jsx global>
{`
@font-face {
font-family: ${config.fontUrl ? config.fontFamily : ''};
src: url(${config.fontUrl || ''}) format('woff');
font-display: swap;
}
`}
</style>
)
}
function isImage(file) {
return file.type.split('/')[0] === 'image'
}

@ -2,11 +2,47 @@
import React from 'react'
import Editor from './Editor'
import { THEMES } from '../lib/constants'
import { getThemes, saveThemes } from '../lib/util'
import Toasts from './Toasts'
import { THEMES, DEFAULT_CODE } from '../lib/constants'
import { updateRouteState } from '../lib/routing'
import { getThemes, saveThemes, clearSettings, saveSettings } from '../lib/util'
import { useAPI } from './ApiContext'
import { useAuth } from './AuthContext'
import { useAsyncCallback } from '@dawnlabs/tacklebox'
function onReset() {
clearSettings()
if (window.navigator && navigator.serviceWorker) {
navigator.serviceWorker.getRegistrations().then(registrations => {
for (let registration of registrations) {
registration.unregister()
}
})
}
}
function toastsReducer(curr, action) {
switch (action.type) {
case 'ADD': {
if (!curr.find(t => t.children === action.toast.children)) {
return curr.concat(action.toast)
}
return curr
}
case 'SET': {
return action.toasts
}
}
throw new Error('Unsupported action')
}
function EditorContainer(props) {
const [themes, updateThemes] = React.useState(THEMES)
const api = useAPI()
const user = useAuth()
const [update, { loading }] = useAsyncCallback(api.snippet.update)
React.useEffect(() => {
const storedThemes = getThemes(localStorage) || []
@ -19,7 +55,67 @@ function EditorContainer(props) {
saveThemes(themes.filter(({ custom }) => custom))
}, [themes])
return <Editor {...props} themes={themes} updateThemes={updateThemes} />
// XXX use context
const [snippet, setSnippet] = React.useState(props.snippet || null)
const [toasts, setToasts] = React.useReducer(toastsReducer, [])
const snippetId = snippet && snippet.id
React.useEffect(() => {
if ('/' + (snippetId || '') === props.router.asPath) {
return
}
props.router.replace('/', '/' + (snippetId || ''), { shallow: true })
}, [snippetId, props.router])
function onEditorUpdate(state) {
if (loading) {
return
}
if (!user) {
updateRouteState(props.router, state)
saveSettings(state)
} else {
const updates = {
...state,
code: state.code != null ? state.code : DEFAULT_CODE
}
if (!snippet) {
update(snippetId, updates).then(newSnippet => {
if (newSnippet && newSnippet.id) {
setSnippet(newSnippet)
setToasts({
type: 'ADD',
toast: { children: 'Snippet saved!', closable: true }
})
}
})
} else if (snippet.userId === user.uid) {
update(snippetId, updates).then(() => {
setToasts({
type: 'ADD',
toast: { children: 'Snippet saved!', closable: true }
})
})
}
}
}
return (
<>
<Toasts toasts={toasts} />
<Editor
{...props}
themes={themes}
updateThemes={updateThemes}
snippet={snippet}
setSnippet={setSnippet}
setToasts={setToasts}
onUpdate={onEditorUpdate}
onReset={onReset}
/>
</>
)
}
export default EditorContainer

@ -141,7 +141,7 @@ function ExportMenu({
</div>
</div>
<div className="save-container">
<span>Save as</span>
<span>Export as</span>
<div>
{!disablePNG && (
<Button

@ -0,0 +1,15 @@
import React from 'react'
export default function FontFace(config) {
return (
<style jsx global>
{`
@font-face {
font-family: ${config.fontUrl ? config.fontFamily : ''};
src: url(${config.fontUrl || ''}) format('woff');
font-display: swap;
}
`}
</style>
)
}

@ -19,14 +19,21 @@ const Footer = () => (
sponsor
</a>
<a className="link" href="https://github.com/carbon-app/carbon/issues/new">
send feedback
feedback
</a>
<a className="link" href="https://github.com/carbon-app/carbon">
source
</a>
<a className="link" href="/terms">
terms
</a>
<a className="link" href="/privacy">
privacy
</a>
</nav>
<div className="mt3 mb2">
a project by{' '}
<div className="mt2 mb2">
created by{' '}
<a className="author-link" href="https://twitter.com/carbon_app">
@carbon_app
</a>{' '}
@ -43,8 +50,13 @@ const Footer = () => (
color: ${COLORS.GRAY};
}
nav {
display: flex;
align-items: center;
}
a {
margin-right: 16px;
margin-right: 1rem;
}
a:last-child {

@ -33,7 +33,7 @@ class ListSetting extends React.Component {
key={item.id}
onClick={this.select.bind(null, item.id)}
>
{this.props.children(item)}
{this.props.children(item, this.props.selected)}
{this.props.selected === item.id ? <Checkmark /> : null}
<style jsx>
{`

@ -0,0 +1,96 @@
import React from 'react'
// import Link from 'next/link'
import firebase, { login, logout } from '../lib/client'
import Button from './Button'
import Popout, { managePopout } from './Popout'
import { useAuth } from './AuthContext'
function Drawer(props) {
return (
<Popout hidden={!props.isVisible} pointerLeft="14px" style={{ width: '180px', left: 0 }}>
<div className="flex">
{/* <Link href="/settings">
<Button large center padding="8px 0">
Settings
</Button>
</Link> */}
<Button large center padding="8px 0" onClick={logout}>
Sign Out
</Button>
</div>
<style jsx>
{`
.flex {
display: flex;
height: 100%;
}
`}
</style>
</Popout>
)
}
function LoginButton({ isVisible, toggleVisibility }) {
const user = useAuth()
if (!firebase) {
return null
}
return (
<div>
<Button
center
border
large
padding="0 16px"
color="white"
className="profile-button"
onClick={() => {
if (!user) {
const provider = new firebase.auth.GithubAuthProvider()
provider.setCustomParameters({
allow_signup: 'true'
})
login(provider)
} else {
toggleVisibility()
}
}}
>
<img
height={20}
src={user ? user.photoURL : '/static/github.svg'}
alt={user ? user.displayName : 'GitHub'}
/>
<span>{user ? user.displayName : 'Sign in/up'}</span>
</Button>
<Drawer isVisible={user && isVisible} />
<style jsx>
{`
div,
div :global(.profile-button) {
position: relative;
height: 100%;
}
div :global(.profile-button) {
max-width: 142px;
min-height: 40px;
}
span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
img {
border-radius: 50%;
margin-right: 16px;
}
`}
</style>
</div>
)
}
export default managePopout(LoginButton)

@ -0,0 +1,47 @@
import React from 'react'
import Button from './Button'
import { COLORS } from '../lib/constants'
import * as Arrows from './svg/Arrows'
const MenuButton = React.memo(({ name, select, selected, noArrows }) => {
return (
<div className="menu-button">
<Button
padding="8px"
onClick={select(name)}
background={selected === name ? COLORS.BLACK : COLORS.DARK_GRAY}
>
{name}
{!noArrows && (
<div className="arrow-icon">
<Arrows.Right />
</div>
)}
</Button>
<style jsx>
{`
.menu-button {
display: flex;
height: 33px;
border-bottom: 1px solid ${COLORS.SECONDARY};
position: relative;
align-items: center;
}
.menu-button:last-child {
${selected === 'Window' ? '' : 'border-bottom: none;'};
}
.arrow-icon {
position: absolute;
right: 14px;
top: 11px;
}
`}
</style>
</div>
)
})
export default MenuButton

@ -1,7 +1,9 @@
import React from 'react'
import AuthContext from './AuthContext'
import Meta from './Meta'
import Header from './Header'
import Footer from './Footer'
import Announcement from './Announcement'
class Page extends React.Component {
render() {
@ -9,8 +11,11 @@ class Page extends React.Component {
return (
<main className="main mt4 mb4">
<Meta />
<Announcement />
<Header enableHeroText={enableHeroText} />
<div className="page">{children}</div>
<AuthContext>
<div className="page">{children}</div>
</AuthContext>
<Footer />

@ -2,13 +2,13 @@ import React from 'react'
import Spinner from 'react-spinner'
import { useAsyncCallback } from '@dawnlabs/tacklebox'
import ApiContext from './ApiContext'
import { useAPI } from './ApiContext'
import PhotoCredit from './PhotoCredit'
function RandomImage(props) {
const cacheRef = React.useRef([])
const [cacheIndex, updateIndex] = React.useState(0)
const api = React.useContext(ApiContext)
const api = useAPI()
const [selectImage, { loading: selecting }] = useAsyncCallback(() => {
const image = cacheRef.current[cacheIndex]

@ -9,10 +9,10 @@ import Toggle from './Toggle'
import Popout, { managePopout } from './Popout'
import Button from './Button'
import Presets from './Presets'
import MenuButton from './MenuButton'
import { COLORS, DEFAULT_PRESETS } from '../lib/constants'
import { toggle, getPresets, savePresets, generateId, fileToJSON } from '../lib/util'
import SettingsIcon from './svg/Settings'
import * as Arrows from './svg/Arrows'
const WindowSettings = React.memo(
({
@ -182,7 +182,6 @@ const MiscSettings = React.memo(({ format, reset, applyPreset, settings }) => {
}}
/>
<Button
width="50%"
center
style={{ borderRight: `1px solid ${COLORS.SECONDARY}` }}
onClick={() => input.current.click()}
@ -219,44 +218,6 @@ const MiscSettings = React.memo(({ format, reset, applyPreset, settings }) => {
)
})
const MenuButton = React.memo(({ name, select, selected }) => {
return (
<div className="menu-button">
<Button
padding="8px"
onClick={select(name)}
background={selected === name ? COLORS.BLACK : COLORS.DARK_GRAY}
>
{name}
<div className="arrow-icon">
<Arrows.Right />
</div>
</Button>
<style jsx>
{`
.menu-button {
display: flex;
height: 33px;
border-bottom: 1px solid ${COLORS.SECONDARY};
position: relative;
align-items: center;
}
.menu-button:last-child {
${selected === 'Window' ? '' : 'border-bottom: none;'};
}
.arrow-icon {
position: absolute;
right: 14px;
top: 11px;
}
`}
</style>
</div>
)
})
const settingButtonStyle = {
width: '40px',
height: '100%'

@ -0,0 +1,104 @@
import React from 'react'
import { useAsyncCallback, useOnline } from '@dawnlabs/tacklebox'
import Button from './Button'
import { useAuth } from './AuthContext'
import Toolbar from './Toolbar'
function ConfirmButton(props) {
const [confirmed, setConfirmed] = React.useState(false)
return (
<Button
{...props}
onClick={e => {
if (confirmed) {
props.onClick(e)
setConfirmed(false)
} else {
setConfirmed(true)
}
}}
onBlur={() => setConfirmed(false)}
>
{confirmed ? 'Are you sure?' : props.children}
</Button>
)
}
function DeleteButton(props) {
const [onClick, { loading }] = useAsyncCallback(props.onClick)
return (
<ConfirmButton
display="block"
padding="0 16px"
flex="unset"
center
border
large
color="#fff"
onClick={onClick}
style={{ color: '#ff5f56' }}
>
{loading ? 'Deleting...' : 'Delete'}
</ConfirmButton>
)
}
function ForkButton(props) {
const [onClick, { loading }] = useAsyncCallback(props.onClick)
// TODO call it duplicate or fork?
return (
<Button
display="block"
padding="0 16px"
margin="0 0 0 1rem"
flex="unset"
center
border
large
color="#37b589"
onClick={onClick}
>
{loading ? 'Duplicating...' : 'Duplicate'}
</Button>
)
}
function SnippetToolbar(props) {
const user = useAuth()
const online = useOnline()
if (!online) {
return null
}
if (!user) {
return null
}
if (!props.snippet) {
return null
}
const sameUser = user.uid === props.snippet.userId
return (
<Toolbar
style={{
marginTop: 16,
marginBottom: 0,
flexDirection: 'row-reverse',
// justifyContent: 'space-between',
zIndex: 1
}}
>
<ForkButton onClick={props.onCreate} />
{sameUser && <DeleteButton onClick={props.onDelete} />}
</Toolbar>
)
}
export default SnippetToolbar

@ -0,0 +1,116 @@
import React from 'react'
function Toast(props) {
const [display, on] = React.useState(true)
function off() {
return on(false)
}
React.useEffect(() => {
if (props.timeout) {
const to = setTimeout(off, props.timeout)
return () => clearTimeout(to)
}
}, [props.timeout])
return (
<div className={`toast mb2 ${display ? '' : 'out'}`}>
<div className="toast-content">
{props.children}
{props.closable && (
<button className="close" onClick={off}>
&times;
</button>
)}
</div>
<style jsx>
{`
@keyframes in {
from {
transform: translateX(16rem);
}
to {
transform: translateX(0rem);
}
}
@keyframes out {
from {
transform: translateX(0rem);
}
97% {
transform: translateX(20rem);
}
to {
transform: translateX(20rem);
display: none;
height: 0;
padding: 0;
margin: 0;
}
}
.toast {
padding: 8px 16px;
color: #fff;
border: 1px solid #fff;
border-radius: 2px;
background: #000;
font-size: 14px;
animation-name: in;
animation-duration: 600ms;
animation-direction: forwards;
animation-fill-mode: both;
animation-timing-function: ease-out;
}
.toast.out {
animation-name: out;
}
.toast-content {
display: flex;
align-items: center;
}
.toast :global(.close) {
padding-left: 0;
padding-right: 0;
background: transparent;
color: white;
border: none;
font-size: 100%;
margin-left: 1rem;
text-decoration: none;
cursor: pointer;
}
`}
</style>
</div>
)
}
function ToastContainer(props) {
return (
<div className="toast">
{props.toasts
.slice()
.reverse()
.map(toast => (
<Toast key={toast.children} {...toast} />
))}
<style jsx>
{`
.toast {
position: fixed;
z-index: 9999;
top: 2rem;
right: 1rem;
}
`}
</style>
</div>
)
}
export default ToastContainer

@ -1,7 +1,7 @@
import React from 'react'
const Toolbar = props => (
<div className="toolbar">
<div className="toolbar" style={props.style}>
{props.children}
<style jsx>
{`

@ -1,11 +1,11 @@
import React from 'react'
import { useAsyncCallback, useOnline as useOnlineListener } from '@dawnlabs/tacklebox'
import ApiContext from './ApiContext'
import { useAPI } from './ApiContext'
import Button from './Button'
function TweetButton(props) {
const api = React.useContext(ApiContext)
const api = useAPI()
const online = useOnlineListener()
const [onClick, { loading }] = useAsyncCallback(props.onClick)

@ -4,18 +4,10 @@ import ms from 'ms'
import { fileToDataURL } from './util'
const client = axios.create({
baseURL: `${process.env.API_URL || ''}/api`
})
const RATE_LIMIT_CODE = 420
const gistClient = axios.create({
baseURL: 'https://api.github.com',
timeout: 5000,
export const client = axios.create({
baseURL: `${process.env.API_URL || ''}/api`,
headers: {
Accept: 'application/vnd.github.v3+json',
'Content-Type': 'application/json'
Accept: 'application/json'
}
})
@ -28,54 +20,28 @@ function tweet(content, encodedImage) {
altText: content
})
.then(res => res.data.url)
.then(url => encodeURIComponent(`Built with @carbon_app ${url}`))
.then(url => encodeURIComponent(`Created with @carbon_app ${url}`))
.then(uri => `https://twitter.com/intent/tweet?text=${uri}`)
.then(openTwitterUrl)
.catch(checkIfRateLimited)
}
function image(state) {
return client.post('/image', { state }).then(res => res.data)
}
// ~ makes the file come later alphabetically, which is how gists are sorted
const CARBON_STORAGE_KEY = '~carbon.json'
async function getGist(uid) {
try {
return await gistClient
.get(`/gists/${uid}`)
.then(res => res.data)
.then(({ id, owner, files }) => {
let config
if (files[CARBON_STORAGE_KEY]) {
try {
config = JSON.parse(files[CARBON_STORAGE_KEY].content)
} catch (error) {
// pass
}
}
const otherFiles = Object.keys(files).filter(key => key !== CARBON_STORAGE_KEY)
const RATE_LIMIT_CODE = 420
function checkIfRateLimited(err) {
if (err.response.status === RATE_LIMIT_CODE) {
alert(
"Oh no! Looks like to many people are trying to tweet right now and we've been rate limited. Try again soon or save and upload manually!"
)
return
}
const snippet = files[otherFiles[0]]
throw err
}
return {
id,
owner,
config: {
...config,
code: snippet.content,
language: snippet.language && snippet.language.toLowerCase()
}
}
})
} catch (e) {
console.error(e)
return null
}
function image(state) {
return client.post('/image', { state }).then(res => res.data)
}
// private
function openTwitterUrl(twitterUrl) {
const width = 575
const height = 400
@ -86,17 +52,6 @@ function openTwitterUrl(twitterUrl) {
window.open(twitterUrl, 'twitter', opts)
}
function checkIfRateLimited(err) {
if (err.response.status === RATE_LIMIT_CODE) {
alert(
"Oh no! Looks like to many people are trying to tweet right now and we've been rate limited. Try again soon or save and upload manually!"
)
return
}
throw err
}
const downloadThumbnailImage = img => {
return client
.get(img.url.replace('http://', 'https://'), { responseType: 'blob' })
@ -115,9 +70,51 @@ const unsplash = {
}
}
function getSnippet(uid, { host } = {}) {
return client
.get(`/snippets/${uid}`, host ? { baseURL: `https://${host}/api` } : undefined)
.then(res => res.data)
.catch(e => {
console.error(e)
return null
})
}
function updateSnippet(uid, data) {
if (uid) {
return client
.patch(`/snippets/${uid}`, data)
.then(res => res.data)
.catch(e => {
console.error(e)
return null
})
}
return client
.post(`/snippets`, data)
.then(res => res.data)
.catch(e => {
console.error(e)
return null
})
}
function deleteSnippet(uid) {
return client
.delete(`/snippets/${uid}`)
.then(res => res.data)
.catch(e => {
console.error(e)
return null
})
}
export default {
gist: {
get: getGist
snippet: {
get: getSnippet,
update: debounce(updateSnippet, ms('1s'), { leading: true, trailing: true }),
create: data => updateSnippet(null, data),
delete: id => deleteSnippet(id)
},
tweet: debounce(tweet, ms('5s'), { leading: true, trailing: false }),
image: debounce(image, ms('5s'), { leading: true, trailing: false }),

@ -0,0 +1,33 @@
import * as firebase from 'firebase/app'
import 'firebase/auth'
if (firebase.apps.length === 0) {
if (process.env.FIREBASE_API_KEY && process.env.FIREBASE_FE_APP_ID) {
firebase.initializeApp({
apiKey: process.env.FIREBASE_API_KEY,
authDomain: `${process.env.FIREBASE_PROJECT_ID}.firebaseapp.com`,
databaseURL: `https://${process.env.FIREBASE_PROJECT_ID}.firebaseio.com`,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: `${process.env.FIREBASE_PROJECT_ID}.appspot.com`,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_FE_APP_ID
})
}
}
export function logout() {
return firebase
.auth()
.signOut()
.catch(console.error)
}
export function login(provider) {
return firebase
.auth()
.setPersistence(firebase.auth.Auth.Persistence.LOCAL)
.then(() => firebase.auth().signInWithPopup(provider))
.catch(console.error)
}
export default firebase.apps.length ? firebase : null

@ -121,7 +121,13 @@ export const getRouteState = router => {
const { asPath = '' } = router
const { query, pathname } = url.parse(asPath, true)
const queryState = getQueryStringState(query)
const path = escapeHtml(pathname.split('/').pop())
const path = escapeHtml(
pathname
// remove trailing slash
.replace(/\/$/, '')
.split('/')
.pop()
)
// TODO fix this hack
const parameter = path.length >= 19 && path.indexOf('.') === -1 && path
@ -148,7 +154,6 @@ export const updateRouteState = (router, state) => {
)
}
// private
const getQueryStringObject = query => {
if (query.state) {
return deserializeState(query.state)

@ -23,6 +23,12 @@ const config = withOffline({
}
}
]
},
env: {
FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
FIREBASE_MESSAGING_SENDER_ID: process.env.FIREBASE_MESSAGING_SENDER_ID,
FIREBASE_FE_APP_ID: process.env.FIREBASE_FE_APP_ID,
FIREBASE_API_KEY: process.env.FIREBASE_API_KEY
}
})

@ -4,6 +4,20 @@
"public": true,
"builds": [{ "src": "package.json", "use": "@now/next" }],
"routes": [
{
"src": "^/privacy/?",
"status": 307,
"headers": {
"Location": "https://www.notion.so/PRIVACY-POLICY-e9847a7777714eb08ba15a7a8eaee937"
}
},
{
"src": "^/terms/?",
"status": 307,
"headers": {
"Location": "https://www.notion.so/TERMS-OF-USE-ff2ce22a7e9848c89c6be46b44297583"
}
},
{ "src": "^/embed(.*)", "dest": "/embed.html" },
{
"src": "^/service-worker.js$",
@ -19,12 +33,26 @@
"cache-control": "public, max-age=43200, immutable"
}
},
{ "handle": "filesystem" },
{ "src": "^/(.*)", "dest": "/index.html" }
{
"src": "^/(.*)/?",
"continue": true,
"headers": {
"X-Frame-Options": "SAMEORIGIN",
"X-XSS-Protection": "1; mode=block",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "no-referrer-when-downgrade",
"Feature-Policy": "geolocation 'self'; microphone 'self'; camera 'self'"
}
},
{ "handle": "filesystem" }
],
"build": {
"env": {
"NODE_ENV": "production"
"NODE_ENV": "production",
"FIREBASE_PROJECT_ID": "@carbon-firebase-project-id",
"FIREBASE_MESSAGING_SENDER_ID": "@carbon-firebase-messaging-sender-id",
"FIREBASE_FE_APP_ID": "@carbon-firebase-fe-app-id",
"FIREBASE_API_KEY": "@carbon-firebase-api-key"
}
},
"github": {

@ -27,17 +27,18 @@
"codemirror-mode-elixir": "^1.1.2",
"codemirror-solidity": "^0.1.6",
"cross-env": "^5.2.0",
"dom-to-image": "^2.5.2",
"dom-to-image": "^2.6.0",
"downshift": "^3.2.12",
"dropperx": "^1.0.1",
"eitherx": "^1.0.2",
"escape-goat": "^2.1.0",
"firebase": "^6.2.0",
"graphql": "^14.3.1",
"highlight.js": "^9.15.9",
"lodash.debounce": "^4.0.8",
"lodash.omitby": "^4.6.0",
"match-sorter": "^4.0.0",
"morphmorph": "^0.1.0",
"morphmorph": "^0.1.2",
"ms": "^2.1.2",
"next": "^9.0.3",
"next-offline": "^4.0.3",
@ -52,8 +53,7 @@
"react-is": "^16.9.0",
"react-spinner": "^0.2.7",
"react-syntax-highlight": "^15.3.1",
"tohash": "^1.0.2",
"url": "^0.11.0"
"tohash": "^1.0.2"
},
"devDependencies": {
"@applitools/eyes-cypress": "^3.6.48",
@ -106,7 +106,6 @@
"type": "git",
"url": "git+https://github.com/carbon-app/carbon.git"
},
"author": "Carbon <@carbon-app>",
"bugs": {
"url": "https://github.com/carbon-app/carbon/issues"
},

@ -0,0 +1,42 @@
import React from 'react'
import Router from 'next/router'
import IndexPage from './index'
import ApiContext from '../components/ApiContext'
import api from '../lib/api'
class IdPage extends React.PureComponent {
static contextType = ApiContext
static async getInitialProps({ req, res, query }) {
const path = query.id
const parameter = path && path.length >= 19 && path.indexOf('.') < 0 && path
let snippet
if (parameter) {
const host = req ? req.headers.host : undefined
snippet = await api.snippet.get(parameter, { host })
if (snippet) {
return { snippet }
}
// 404 Not found
if (res) {
res.writeHead(302, {
Location: '/'
})
res.end()
} else {
Router.push('/')
}
}
return {}
}
render() {
return <IndexPage {...this.props} />
}
}
export default IdPage

@ -4,15 +4,13 @@ import Document, { Head, Main, NextScript } from 'next/document'
export default class extends Document {
render() {
return (
<React.StrictMode>
<html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</html>
</React.StrictMode>
<html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}

@ -42,18 +42,21 @@ class Embed extends React.Component {
readOnly: true
}
snippet = {}
async componentDidMount() {
const { queryState, parameter } = getRouteState(this.props.router)
let gistState
if (this.context.gist && parameter) {
const gist = await this.context.gist.get(parameter)
gistState = gist && gist.config
if (parameter) {
const snippet = await this.context.snippet.get(parameter)
if (snippet) {
this.snippet = snippet
}
}
this.setState(
{
...gistState,
...this.snippet,
...queryState,
copyable: queryState.copy !== false,
readOnly: queryState.readonly !== false,

@ -2,15 +2,12 @@
import React from 'react'
import { withRouter } from 'next/router'
import { register, unregister } from 'next-offline/runtime'
import debounce from 'lodash.debounce'
import Either from 'eitherx'
// Ours
import EditorContainer from '../components/EditorContainer'
import Page from '../components/Page'
import { MetaLinks } from '../components/Meta'
import { updateRouteState } from '../lib/routing'
import { saveSettings, clearSettings } from '../lib/util'
class Index extends React.Component {
componentDidMount() {
@ -22,25 +19,12 @@ class Index extends React.Component {
shouldComponentUpdate = () => false
onEditorUpdate = debounce(
state => {
updateRouteState(this.props.router, state)
saveSettings(state)
},
750,
{ trailing: true, leading: true }
)
render() {
return (
<Page enableHeroText={true}>
<MetaLinks />
<Either>
<EditorContainer
router={this.props.router}
onUpdate={this.onEditorUpdate}
onReset={onReset}
/>
<EditorContainer router={this.props.router} snippet={this.props.snippet} />
<p>
An unexpected error has occurred. Please{' '}
<u>
@ -54,16 +38,4 @@ class Index extends React.Component {
}
}
function onReset() {
clearSettings()
if (window.navigator && navigator.serviceWorker) {
navigator.serviceWorker.getRegistrations().then(registrations => {
for (let registration of registrations) {
registration.unregister()
}
})
}
}
export default withRouter(Index)

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="white" d="M256 32C132.3 32 32 134.9 32 261.7c0 101.5 64.2 187.5 153.2 217.9 1.4.3 2.6.4 3.8.4 8.3 0 11.5-6.1 11.5-11.4 0-5.5-.2-19.9-.3-39.1-8.4 1.9-15.9 2.7-22.6 2.7-43.1 0-52.9-33.5-52.9-33.5-10.2-26.5-24.9-33.6-24.9-33.6-19.5-13.7-.1-14.1 1.4-14.1h.1c22.5 2 34.3 23.8 34.3 23.8 11.2 19.6 26.2 25.1 39.6 25.1 10.5 0 20-3.4 25.6-6 2-14.8 7.8-24.9 14.2-30.7-49.7-5.8-102-25.5-102-113.5 0-25.1 8.7-45.6 23-61.6-2.3-5.8-10-29.2 2.2-60.8 0 0 1.6-.5 5-.5 8.1 0 26.4 3.1 56.6 24.1 17.9-5.1 37-7.6 56.1-7.7 19 .1 38.2 2.6 56.1 7.7 30.2-21 48.5-24.1 56.6-24.1 3.4 0 5 .5 5 .5 12.2 31.6 4.5 55 2.2 60.8 14.3 16.1 23 36.6 23 61.6 0 88.2-52.4 107.6-102.3 113.3 8 7.1 15.2 21.1 15.2 42.5 0 30.7-.3 55.5-.3 63 0 5.4 3.1 11.5 11.4 11.5 1.2 0 2.6-.1 4-.4C415.9 449.2 480 363.1 480 261.7 480 134.9 379.7 32 256 32z"/></svg>

After

Width:  |  Height:  |  Size: 882 B

@ -931,6 +931,177 @@
react-click-outside "^3.0.1"
react-fast-compare "2.0.4"
"@firebase/app-types@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.4.0.tgz#bb2c651f3b275fef549050cff28af752839c75c0"
integrity sha512-8erNMHc0V26gA6Nj4W9laVrQrXHsj9K2TEM7eL2IQogGSHLL4vet3UNekYfcGQ2cjfvwUjMzd+BNS/8S7GnfiA==
"@firebase/app@0.4.10":
version "0.4.10"
resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.4.10.tgz#3897a8ef4baa3faa39298e62488aa489b03921e0"
integrity sha512-w1Dc3zNNluDq4IYzTSKoO2kgNgVMiaBB3ki2OfHwhnfPh0H5WbIGOF5dLepk56iBsZjiRvpmHgDQbjLyI9foEQ==
dependencies:
"@firebase/app-types" "0.4.0"
"@firebase/logger" "0.1.18"
"@firebase/util" "0.2.21"
dom-storage "2.1.0"
tslib "1.9.3"
xmlhttprequest "1.8.0"
"@firebase/auth-types@0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.7.0.tgz#8aac4b9c04aff61362827c35b5ad36db16a837ba"
integrity sha512-QEG9azYwssGWcb4NaKFHe3Piez0SG46nRlu76HM4/ob0sjjNpNTY1Z5C3IoeJYknp2kMzuQi0TTW8tjEgkUAUA==
"@firebase/auth@0.11.4":
version "0.11.4"
resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.11.4.tgz#13e47bded49f49bb590684c190891e43eb76c984"
integrity sha512-wYWmqYiP7nsH9LE0lMFDgea/TbTNpQi6Ilx/CaTMiaBMGnbDIeUGsTFQ0lrk5STvEL5UOGVyxG0ZPEgpc98mbQ==
dependencies:
"@firebase/auth-types" "0.7.0"
"@firebase/database-types@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.4.0.tgz#71a711a3f666fac905422e130731930e2bcca582"
integrity sha512-2piRYW7t+2s/P1NPpcI/3+8Y5l2WnJhm9KACoXW5zmoAPlya8R1aEaR2dNHLNePTMHdg04miEDD9fEz4xUqzZA==
"@firebase/database@0.4.7":
version "0.4.7"
resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.4.7.tgz#9ca0d94b3090cf87bdc3d6f5b6be934100611462"
integrity sha512-ZMnn3cliGzz/P2/lCDhZQK2q/wh1THWu6/kYMAO9QnaZGL5842iPKVIvl8D4rOxfZga0bNLGqkZW7zPb3LHCDw==
dependencies:
"@firebase/database-types" "0.4.0"
"@firebase/logger" "0.1.18"
"@firebase/util" "0.2.21"
faye-websocket "0.11.3"
tslib "1.9.3"
"@firebase/firestore-types@1.4.2":
version "1.4.2"
resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-1.4.2.tgz#006041fc914a200c48780e9339e0ff5f9bcaaabd"
integrity sha512-Kypan1Ch7u3otPAnZ4M5ugeN64IG1kjXRrc8bgGy3hN2bWzoLZ8DeiF/2PmdswlnEvD77koLyyz2zpagWFe8YA==
"@firebase/firestore@1.4.4":
version "1.4.4"
resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-1.4.4.tgz#8a56b35eff14a514bd13af8131577c4ee473d90a"
integrity sha512-WFuKYOsOlYowyHjazUkzVhmPTuqDXbGv1AAgncPVfuioEoAGCK2KY4OGQkmyAfbg6juYU3nUNcmcY3yQSHfy+w==
dependencies:
"@firebase/firestore-types" "1.4.2"
"@firebase/logger" "0.1.18"
"@firebase/util" "0.2.21"
"@firebase/webchannel-wrapper" "0.2.21"
"@grpc/proto-loader" "^0.5.0"
grpc "1.20.3"
tslib "1.9.3"
"@firebase/functions-types@0.3.6":
version "0.3.6"
resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.3.6.tgz#27516f986ec0fad71d39797a8869d08b970c4123"
integrity sha512-OIWXsaUBNSA7ifkrTFKwNMDgs1DCk6dC7xwofRBIrJP3ZxLPxRV79KyKKqcThe5Ie6JeG6oyFAIK5CMTYa5Ebg==
"@firebase/functions@0.4.11":
version "0.4.11"
resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.4.11.tgz#973a3cc6af6a54c6fab04447911036b7aca7ff6c"
integrity sha512-p/Al2EmMpwMZapG6bDr1C/eTOqSyLJbNTB8HDrfzoSHHhvCKHGBZIUC03j/6h4kMJNwWGSxqt9fhkTS7xvZgZQ==
dependencies:
"@firebase/functions-types" "0.3.6"
"@firebase/messaging-types" "0.3.0"
isomorphic-fetch "2.2.1"
tslib "1.9.3"
"@firebase/installations-types@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.1.1.tgz#630a57705f84df206af7f3b51781898864e97dbd"
integrity sha512-M+plQIOt6p+/j/ExUgsfXe1JFAKymhBU0K3+cp7hzj52vLSpklOqNJi4LkFl41pgRFPZeKf7MrTkMhVowg3Ukw==
"@firebase/installations@0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.2.0.tgz#692c2c81a18a02b6d4141a64a83623fc4da3aacc"
integrity sha512-bjpOc02WMZT5z2tNqqLgOBWcbm9mU40vWfJXZc4B+Y6///shmR4EPmUmacjkCBzYjVJy//aBLi4u9P7SuqV7ag==
dependencies:
"@firebase/installations-types" "0.1.1"
"@firebase/util" "0.2.21"
idb "3.0.2"
tslib "1.9.3"
"@firebase/logger@0.1.18":
version "0.1.18"
resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.1.18.tgz#5b0a849e32dfc0fdb7be9043cf1ae5584902949a"
integrity sha512-/2l28mC9xPXi3Kqe/xUJ/vQ8h4NalwAiYkNihE/JogkzluhqON17ton8OezcZ+gjq12mF9Oq2Xd9WxplMXK6vA==
"@firebase/messaging-types@0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@firebase/messaging-types/-/messaging-types-0.3.0.tgz#915eca1a6c1e0ceacf82e5086724cf054976b997"
integrity sha512-xCFMPy4C+WXFcshTnQEyddmqM6ZkzpTeJq7RUhrAvUnjlfFzOB92HOfKtjT6IpNk5W+jNbTTrqgrgReuPXsM2A==
"@firebase/messaging@0.4.4":
version "0.4.4"
resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.4.4.tgz#c7dd696db52b4221eda38e22797f98dfc2fcc390"
integrity sha512-j50hwkXxQh2fEsncGkfqMk+PgSNUHtZPE5mlCTpiANS24zqelO/V19NRmhYdYeC3wTsh79cgAHlJFSvN2KIXZA==
dependencies:
"@firebase/messaging-types" "0.3.0"
"@firebase/util" "0.2.21"
tslib "1.9.3"
"@firebase/performance-types@0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.0.2.tgz#4e37183f99c937cda7683ef3831e723c5cbf7e5f"
integrity sha512-nIZMVqc3tAGqRmNUU43yQ/WKY5Sypysa4Xg6J5F0q+QqxPpgwDh5xiPLEvD+/k6rswVTYQ9tsuIWqcJNpbA9zw==
"@firebase/performance@0.2.11":
version "0.2.11"
resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.2.11.tgz#89b971ab25be1138f0df2997ee4089d00eed35a8"
integrity sha512-xr2KTGn9MiHXt4FbaSYPsWe3qkm1qYelFPUPaooXPlBc6sdkyMyko8JqwXST4Pa5F/Fgm0Mvxiu2V0LhRXmbow==
dependencies:
"@firebase/installations" "0.2.0"
"@firebase/logger" "0.1.18"
"@firebase/performance-types" "0.0.2"
"@firebase/util" "0.2.21"
tslib "1.9.3"
"@firebase/polyfill@0.3.15":
version "0.3.15"
resolved "https://registry.yarnpkg.com/@firebase/polyfill/-/polyfill-0.3.15.tgz#ec44ebdc63d51d93ce707ccf9f7df0b4d1a11961"
integrity sha512-SDeH1UTQRtVUYQbbC9hiqZ3y8fDbsbYV9+Z8JN2NB8OL3ahh4hBhIwQwzBac5A/EqCBNJUMNeUEU4rLcC3uG3A==
dependencies:
core-js "3.0.1"
promise-polyfill "8.1.0"
whatwg-fetch "2.0.4"
"@firebase/storage-types@0.3.1":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.3.1.tgz#a85f115b6c51fc3a75bca5858061f6c84c0b845c"
integrity sha512-Vuf7/nSTWrvPmoZiwfQjI3ThqAKQXVLpozhoGVxoGM1qtITsnw+Oe/Fa+CW1/ZkelVBcy8ZWEB2aaHXaDu3h+Q==
"@firebase/storage@0.3.5":
version "0.3.5"
resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.3.5.tgz#d9f774c6a9db1416c823c90d986598ac3c6c35ab"
integrity sha512-1zgmLaHNRSA/ukYLeYRfqr7PsSrJe0OsF0X5Fu0TsDagV78qrSyJqMljKaGr9t3PTvBo0LEgVEBJUkpAgp+fwA==
dependencies:
"@firebase/storage-types" "0.3.1"
"@firebase/util" "0.2.21"
tslib "1.9.3"
"@firebase/util@0.2.21":
version "0.2.21"
resolved "https://registry.yarnpkg.com/@firebase/util/-/util-0.2.21.tgz#b9a592d6381efbc526ea8b07ec94875800935f64"
integrity sha512-80ZblYuorX4Udr4wPzht1upQzk99xS2SIRfl4gvTNiu5WXKTSKKk5WbpiR8IL2bYVSo/dd634B2L7BOTEjHcqA==
dependencies:
tslib "1.9.3"
"@firebase/webchannel-wrapper@0.2.21":
version "0.2.21"
resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.21.tgz#1116075d3d821e058a8c321385552c51fa3a6680"
integrity sha512-eL4xPPjTBceYKa27tN3SahSD/7k5ioKFGeZZZX67+aLuxxFts2eTCcotRAeKcjGu1xTz7GnWUkMsj4NZZTIGXg==
"@grpc/proto-loader@^0.5.0":
version "0.5.1"
resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.1.tgz#48492b53cdda353110b51a4b02f465974729c76f"
integrity sha512-3y0FhacYAwWvyXshH18eDkUI40wT/uGio7MAegzY8lO5+wVsc19+1A7T0pPptae4kl7bdITL+0cHpnAPmryBjQ==
dependencies:
lodash.camelcase "^4.3.0"
protobufjs "^6.8.6"
"@hapi/address@2.x.x":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a"
@ -1147,6 +1318,59 @@
"@nodelib/fs.scandir" "2.1.1"
fastq "^1.6.0"
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
"@protobufjs/base64@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
"@protobufjs/codegen@^2.0.4":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
"@protobufjs/eventemitter@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
"@protobufjs/fetch@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
dependencies:
"@protobufjs/aspromise" "^1.1.1"
"@protobufjs/inquire" "^1.1.0"
"@protobufjs/float@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
"@protobufjs/inquire@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
"@protobufjs/path@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
"@protobufjs/pool@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
"@protobufjs/utf8@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
"@reach/visually-hidden@^0.1.4":
version "0.1.4"
resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.1.4.tgz#0dc4ecedf523004337214187db70a46183bd945b"
@ -1226,6 +1450,11 @@
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
"@types/long@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.0.tgz#719551d2352d301ac8b81db732acb6bdc28dbdef"
integrity sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@ -1236,6 +1465,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.8.tgz#e469b4bf9d1c9832aee4907ba8a051494357c12c"
integrity sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==
"@types/node@^10.1.0":
version "10.14.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.12.tgz#0eec3155a46e6c4db1f27c3e588a205f767d622f"
integrity sha512-QcAKpaO6nhHLlxWBvpc4WeLrTvPqlHOvaj0s5GriKkA1zq+bsFBPpfYCvQhLqLgYlIko8A9YrPdaMHCo5mBcpg==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
@ -1738,6 +1972,14 @@ asap@~2.0.3:
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
ascli@~1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ascli/-/ascli-1.0.1.tgz#bcfa5974a62f18e81cabaeb49732ab4a88f906bc"
integrity sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=
dependencies:
colour "~0.7.1"
optjs "~3.2.2"
asn1.js@^4.0.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
@ -2248,6 +2490,13 @@ builtin-status-codes@^3.0.0:
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
bytebuffer@~5:
version "5.0.1"
resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd"
integrity sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=
dependencies:
long "~3"
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
@ -2343,6 +2592,11 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
camelcase@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
camelcase@^5.0.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
@ -2506,6 +2760,15 @@ clipboardy@^1.2.3:
arch "^2.1.0"
execa "^0.8.0"
cliui@^3.0.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrap-ansi "^2.0.0"
cliui@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
@ -2584,6 +2847,11 @@ colors@1.1.2:
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM=
colour@~0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778"
integrity sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@ -2766,6 +3034,11 @@ core-js-pure@3.1.4:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.1.4.tgz#5fa17dc77002a169a3566cc48dc774d2e13e3769"
integrity sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA==
core-js@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.1.tgz#1343182634298f7f38622f95e73f54e48ddf4738"
integrity sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==
core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5:
version "2.6.9"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
@ -3010,7 +3283,7 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
dependencies:
ms "^2.1.1"
decamelize@^1.2.0:
decamelize@^1.1.1, decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@ -3185,7 +3458,12 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
dom-to-image@^2.5.2:
dom-storage@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/dom-storage/-/dom-storage-2.1.0.tgz#00fb868bc9201357ea243c7bcfd3304c1e34ea39"
integrity sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==
dom-to-image@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/dom-to-image/-/dom-to-image-2.6.0.tgz#8a503608088c87b1c22f9034ae032e1898955867"
integrity sha1-ilA2CAiMh7HCL5A0rgMuGJiVWGc=
@ -3295,6 +3573,13 @@ encodeurl@~1.0.1, encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
dependencies:
iconv-lite "~0.4.13"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
@ -3924,6 +4209,13 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.0"
faye-websocket@0.11.3:
version "0.11.3"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e"
integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==
dependencies:
websocket-driver ">=0.5.1"
fb-watchman@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
@ -4066,6 +4358,24 @@ find-up@^4.0.0:
locate-path "^5.0.0"
path-exists "^4.0.0"
firebase@^6.2.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/firebase/-/firebase-6.3.0.tgz#1998c111f2d6c80ccec432e7b89010a2d553ca5e"
integrity sha512-yXes80Z//0Dpnet7OfpcUkvyJpBtVaqTHqqMAZ4QrINuKfNOyjF5E/Xpbw8DMVHTJ5netjTLKfmUNvXQJLGs8A==
dependencies:
"@firebase/app" "0.4.10"
"@firebase/app-types" "0.4.0"
"@firebase/auth" "0.11.4"
"@firebase/database" "0.4.7"
"@firebase/firestore" "1.4.4"
"@firebase/functions" "0.4.11"
"@firebase/installations" "0.2.0"
"@firebase/messaging" "0.4.4"
"@firebase/performance" "0.2.11"
"@firebase/polyfill" "0.3.15"
"@firebase/storage" "0.3.5"
"@firebase/util" "0.2.21"
flat-cache@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
@ -4317,7 +4627,7 @@ glob-to-regexp@^0.4.1:
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.3:
glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.3:
version "7.1.4"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
@ -4458,6 +4768,17 @@ growly@^1.3.0:
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
grpc@1.20.3:
version "1.20.3"
resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.20.3.tgz#a74d36718f1e89c4a64f2fb9441199c3c8f78978"
integrity sha512-GsEsi0NVj6usS/xor8pF/xDbDiwZQR59aZl5NUZ59Sy2bdPQFZ3UePr5wevZjHboirRCIQCKRI1cCgvSWUe2ag==
dependencies:
lodash.camelcase "^4.3.0"
lodash.clone "^4.5.0"
nan "^2.13.2"
node-pre-gyp "^0.13.0"
protobufjs "^5.0.3"
gzip-size@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
@ -4649,6 +4970,11 @@ http-errors@~1.7.2:
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
"http-parser-js@>=0.4.0 <0.4.11":
version "0.4.10"
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4"
integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@ -4687,13 +5013,18 @@ husky@^3.0.3:
run-node "^1.0.0"
slash "^3.0.0"
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
dependencies:
safer-buffer ">= 2.1.2 < 3"
idb@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/idb/-/idb-3.0.2.tgz#c8e9122d5ddd40f13b60ae665e4862f8b13fa384"
integrity sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==
ieee754@^1.1.4:
version "1.1.13"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
@ -4826,6 +5157,11 @@ invariant@^2.2.2, invariant@^2.2.4:
dependencies:
loose-envify "^1.0.0"
invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
invert-kv@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
@ -5087,7 +5423,7 @@ is-regexp@^1.0.0:
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
is-stream@^1.1.0:
is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
@ -5141,6 +5477,14 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
isomorphic-fetch@2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
dependencies:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@ -5778,6 +6122,13 @@ lazy-ass@1.6.0:
resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513"
integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM=
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
dependencies:
invert-kv "^1.0.0"
lcid@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
@ -5979,6 +6330,16 @@ lodash._reinterpolate@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
lodash.clone@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6"
integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=
lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@ -6082,6 +6443,16 @@ log-update@^2.3.0:
cli-cursor "^2.0.0"
wrap-ansi "^3.0.1"
long@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
long@~3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
integrity sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@ -6402,7 +6773,7 @@ moment@2.24.0:
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
morphmorph@^0.1.0:
morphmorph@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/morphmorph/-/morphmorph-0.1.2.tgz#d95dcf68b112c0e89506fff3b4bed4f907bc7700"
integrity sha512-8DPqe7bKUjaWRWGG6x9hVcW2FvuPQH0PpPkHs7Gi8mtTjyYkvf2yA2UlULKFuvjpkkcef2TixXEYDG949CJnug==
@ -6439,7 +6810,7 @@ mute-stream@0.0.7:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
nan@^2.12.1:
nan@^2.12.1, nan@^2.13.2:
version "2.14.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
@ -6584,6 +6955,14 @@ node-fetch@2.6.0, node-fetch@^2.3.0, node-fetch@^2.6.0:
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
node-int64@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
@ -6650,6 +7029,22 @@ node-pre-gyp@^0.12.0:
semver "^5.3.0"
tar "^4"
node-pre-gyp@^0.13.0:
version "0.13.0"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz#df9ab7b68dd6498137717838e4f92a33fc9daa42"
integrity sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==
dependencies:
detect-libc "^1.0.2"
mkdirp "^0.5.1"
needle "^2.2.1"
nopt "^4.0.1"
npm-packlist "^1.1.6"
npmlog "^4.0.2"
rc "^1.2.7"
rimraf "^2.6.1"
semver "^5.3.0"
tar "^4"
node-releases@^1.1.25:
version "1.1.25"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.25.tgz#0c2d7dbc7fed30fbe02a9ee3007b8c90bf0133d3"
@ -6906,6 +7301,11 @@ optionator@^0.8.1, optionator@^0.8.2:
type-check "~0.3.2"
wordwrap "~1.0.0"
optjs@~3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/optjs/-/optjs-3.2.2.tgz#69a6ce89c442a44403141ad2f9b370bd5bb6f4ee"
integrity sha1-aabOicRCpEQDFBrS+bNwvVu29O4=
ora@^0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4"
@ -6926,6 +7326,13 @@ os-homedir@^1.0.0, os-homedir@^1.0.1:
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
os-locale@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=
dependencies:
lcid "^1.0.0"
os-locale@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
@ -7364,6 +7771,11 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
promise-polyfill@8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.0.tgz#30059da54d1358ce905ac581f287e184aedf995d"
integrity sha512-OzSf6gcCUQ01byV4BgwyUCswlaQQ6gzXc23aLQWhicvfX9kfsUiUhgt3CCQej8jDnl8/PhGF31JdHX2/MzF3WA==
promise@7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
@ -7405,6 +7817,35 @@ prop-types@15.7.2, prop-types@>=15.5.8, prop-types@^15.5.10, prop-types@^15.5.8,
object-assign "^4.1.1"
react-is "^16.8.1"
protobufjs@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-5.0.3.tgz#e4dfe9fb67c90b2630d15868249bcc4961467a17"
integrity sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==
dependencies:
ascli "~1"
bytebuffer "~5"
glob "^7.0.5"
yargs "^3.10.0"
protobufjs@^6.8.6:
version "6.8.8"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.8.tgz#c8b4f1282fd7a90e6f5b109ed11c84af82908e7c"
integrity sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==
dependencies:
"@protobufjs/aspromise" "^1.1.2"
"@protobufjs/base64" "^1.1.2"
"@protobufjs/codegen" "^2.0.4"
"@protobufjs/eventemitter" "^1.1.0"
"@protobufjs/fetch" "^1.1.0"
"@protobufjs/float" "^1.0.2"
"@protobufjs/inquire" "^1.1.0"
"@protobufjs/path" "^1.1.2"
"@protobufjs/pool" "^1.1.0"
"@protobufjs/utf8" "^1.1.0"
"@types/long" "^4.0.0"
"@types/node" "^10.1.0"
long "^4.0.0"
proxy-addr@~2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
@ -8031,7 +8472,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2:
safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2:
version "5.2.0"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
@ -8904,6 +9345,11 @@ tryer@^1.0.1:
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
tslib@1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
tslib@^1.9.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
@ -9324,6 +9770,20 @@ webpack@^4.19.1, webpack@^4.33.0:
watchpack "^1.5.0"
webpack-sources "^1.3.0"
websocket-driver@>=0.5.1:
version "0.7.3"
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9"
integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==
dependencies:
http-parser-js ">=0.4.0 <0.4.11"
safe-buffer ">=5.1.0"
websocket-extensions ">=0.1.1"
websocket-extensions@>=0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
@ -9383,6 +9843,11 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2 || 2"
window-size@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876"
integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
@ -9619,11 +10084,21 @@ xmlchars@^2.1.1:
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.1.1.tgz#ef1a81c05bff629c2280007f12daca21bd6f6c93"
integrity sha512-7hew1RPJ1iIuje/Y01bGD/mXokXxegAgVS+e+E0wSi2ILHQkYAH1+JXARwTjZSM4Z4Z+c73aKspEcqj+zPPL/w==
xmlhttprequest@1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
y18n@^3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
@ -9689,6 +10164,19 @@ yargs@^13.1.0:
y18n "^4.0.0"
yargs-parser "^13.1.1"
yargs@^3.10.0:
version "3.32.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995"
integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=
dependencies:
camelcase "^2.0.1"
cliui "^3.0.3"
decamelize "^1.1.1"
os-locale "^1.4.0"
string-width "^1.0.1"
window-size "^0.1.4"
y18n "^3.2.0"
yauzl@2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"

Loading…
Cancel
Save