Handle daemon startup errors/timeouts #2098
8 changed files with 197 additions and 44 deletions
2
flow-typed/i18n.js
vendored
2
flow-typed/i18n.js
vendored
|
@ -1 +1 @@
|
||||||
declare function __(a: string): string;
|
declare function __(a: string, b?: string | number): string;
|
||||||
|
|
|
@ -22,7 +22,6 @@ class ToolTip extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.tooltip = React.createRef();
|
|
||||||
this.state = {
|
this.state = {
|
||||||
direction: this.props.direction,
|
direction: this.props.direction,
|
||||||
};
|
};
|
||||||
|
@ -33,11 +32,11 @@ class ToolTip extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
getVisibility = () => {
|
getVisibility = () => {
|
||||||
if (!this.tooltip.current) {
|
if (!this.tooltip) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const node = this.tooltip.current;
|
const node = this.tooltip;
|
||||||
const rect = node.getBoundingClientRect();
|
const rect = node.getBoundingClientRect();
|
||||||
|
|
||||||
// Get parent-container
|
// Get parent-container
|
||||||
|
@ -80,12 +79,12 @@ class ToolTip extends React.PureComponent<Props, State> {
|
||||||
const visibility = this.getVisibility();
|
const visibility = this.getVisibility();
|
||||||
|
|
||||||
// Invert direction if tooltip is outside viewport bounds
|
// Invert direction if tooltip is outside viewport bounds
|
||||||
if (!visibility[direction]) {
|
if (!visibility || !visibility[direction]) {
|
||||||
this.invertDirection();
|
this.invertDirection();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tooltip: { current: null | HTMLSpanElement };
|
tooltip: ?HTMLSpanElement;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { direction } = this.state;
|
const { direction } = this.state;
|
||||||
|
@ -111,7 +110,9 @@ class ToolTip extends React.PureComponent<Props, State> {
|
||||||
>
|
>
|
||||||
{tooltipContent}
|
{tooltipContent}
|
||||||
<span
|
<span
|
||||||
ref={this.tooltip}
|
ref={ref => {
|
||||||
|
this.tooltip = ref;
|
||||||
|
}}
|
||||||
className={classnames('tooltip__body', {
|
className={classnames('tooltip__body', {
|
||||||
'tooltip__body--short': isShortDescription,
|
'tooltip__body--short': isShortDescription,
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import Spinner from 'component/spinner';
|
import Spinner from 'component/spinner';
|
||||||
|
import Button from 'component/button';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
message: string,
|
message: string,
|
||||||
details: ?string,
|
details: ?string,
|
||||||
isWarning: boolean,
|
isWarning: boolean,
|
||||||
|
error: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoadScreen extends React.PureComponent<Props> {
|
class LoadScreen extends React.PureComponent<Props> {
|
||||||
|
@ -16,7 +18,7 @@ class LoadScreen extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { details, message, isWarning } = this.props;
|
const { details, message, isWarning, error } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="load-screen">
|
<div className="load-screen">
|
||||||
|
@ -24,17 +26,42 @@ class LoadScreen extends React.PureComponent<Props> {
|
||||||
<h1 className="load-screen__title">{__('LBRY')}</h1>
|
<h1 className="load-screen__title">{__('LBRY')}</h1>
|
||||||
<sup className="load-screen__beta">beta</sup>
|
<sup className="load-screen__beta">beta</sup>
|
||||||
</div>
|
</div>
|
||||||
{isWarning ? (
|
{error ? (
|
||||||
<span className="load-screen__message">
|
<Fragment>
|
||||||
<Icon size={20} icon={icons.ALERT} />
|
<h3>{__('Uh oh. Sean must have messed something up. Try refreshing to fix it.')}</h3>
|
||||||
{` ${message}`}
|
<div className="card__actions">
|
||||||
</span>
|
<Button label="Refresh" button="alt" onClick={() => window.location.reload()} />
|
||||||
|
</div>
|
||||||
|
<div className="load-screen--help">
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
'If you still have issues, your anti-virus software or firewall may be preventing startup.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{__('Reach out to hello@lbry.io for help, or check out')}{' '}
|
||||||
|
<Button
|
||||||
|
className="btn--load-screen"
|
||||||
|
href="https://lbry.io/faq/startup-troubleshooting"
|
||||||
|
label="this link"
|
||||||
|
/>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
) : (
|
) : (
|
||||||
<div className="load-screen__message">{message}</div>
|
<Fragment>
|
||||||
|
{isWarning ? (
|
||||||
|
<span className="load-screen__message">
|
||||||
|
<Icon size={20} icon={icons.ALERT} />
|
||||||
|
{` ${message}`}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<div className="load-screen__message">{message}</div>
|
||||||
|
)}
|
||||||
|
{details && <div className="load-screen__details">{details}</div>}
|
||||||
|
<Spinner type="splash" />
|
||||||
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{details && <div className="load-screen__details">{details}</div>}
|
|
||||||
<Spinner type="splash" />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import type { Status } from 'types/status';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Lbry, MODALS } from 'lbry-redux';
|
import { Lbry, MODALS } from 'lbry-redux';
|
||||||
import ModalWalletUnlock from 'modal/modalWalletUnlock';
|
import ModalWalletUnlock from 'modal/modalWalletUnlock';
|
||||||
|
@ -7,6 +8,8 @@ import ModalUpgrade from 'modal/modalUpgrade';
|
||||||
import ModalDownloading from 'modal/modalDownloading';
|
import ModalDownloading from 'modal/modalDownloading';
|
||||||
import LoadScreen from './internal/load-screen';
|
import LoadScreen from './internal/load-screen';
|
||||||
|
|
||||||
|
const ONE_MINUTE = 60 * 1000;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
checkDaemonVersion: () => Promise<any>,
|
checkDaemonVersion: () => Promise<any>,
|
||||||
notifyUnlockWallet: () => Promise<any>,
|
notifyUnlockWallet: () => Promise<any>,
|
||||||
|
@ -23,6 +26,7 @@ type State = {
|
||||||
message: string,
|
message: string,
|
||||||
isRunning: boolean,
|
isRunning: boolean,
|
||||||
launchedModal: boolean,
|
launchedModal: boolean,
|
||||||
|
error: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export class SplashScreen extends React.PureComponent<Props, State> {
|
export class SplashScreen extends React.PureComponent<Props, State> {
|
||||||
|
@ -34,14 +38,17 @@ export class SplashScreen extends React.PureComponent<Props, State> {
|
||||||
message: __('Connecting'),
|
message: __('Connecting'),
|
||||||
isRunning: false,
|
isRunning: false,
|
||||||
launchedModal: false,
|
launchedModal: false,
|
||||||
|
error: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.hasRecordedUser = false;
|
this.hasRecordedUser = false;
|
||||||
|
this.timeout = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { checkDaemonVersion } = this.props;
|
const { checkDaemonVersion } = this.props;
|
||||||
|
|
||||||
|
this.adjustErrorTimeout();
|
||||||
Lbry.connect()
|
Lbry.connect()
|
||||||
.then(checkDaemonVersion)
|
.then(checkDaemonVersion)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -57,22 +64,54 @@ export class SplashScreen extends React.PureComponent<Props, State> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.adjustErrorTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.timeout) {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustErrorTimeout() {
|
||||||
|
if (this.timeout) {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every time we make it to a new step in the daemon startup process, reset the timer
|
||||||
|
// If nothing changes after 1 minute, show the error message.
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.setState({ error: true });
|
||||||
|
}, ONE_MINUTE);
|
||||||
|
}
|
||||||
|
|
||||||
updateStatus() {
|
updateStatus() {
|
||||||
Lbry.status().then(status => {
|
Lbry.status().then(status => {
|
||||||
this.updateStatusCallback(status);
|
this.updateStatusCallback(status);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatusCallback(status) {
|
updateStatusCallback(status: Status) {
|
||||||
const { notifyUnlockWallet, authenticate } = this.props;
|
const { notifyUnlockWallet, authenticate } = this.props;
|
||||||
const { launchedModal } = this.state;
|
const { launchedModal } = this.state;
|
||||||
|
|
||||||
|
if (status.error) {
|
||||||
|
this.setState({
|
||||||
|
error: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.hasRecordedUser && status) {
|
if (!this.hasRecordedUser && status) {
|
||||||
authenticate();
|
authenticate();
|
||||||
this.hasRecordedUser = true;
|
this.hasRecordedUser = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.wallet && status.wallet.is_locked) {
|
const { wallet, blockchain_headers: blockchainHeaders } = status;
|
||||||
|
|
||||||
|
// If the wallet is locked, stop doing anything and make the user input their password
|
||||||
|
if (wallet && wallet.is_locked) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isRunning: true,
|
isRunning: true,
|
||||||
});
|
});
|
||||||
|
@ -97,43 +136,49 @@ export class SplashScreen extends React.PureComponent<Props, State> {
|
||||||
this.props.onReadyToLaunch();
|
this.props.onReadyToLaunch();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (status.blockchain_headers && status.blockchain_headers.download_progress < 100) {
|
} else if (blockchainHeaders) {
|
||||||
|
const blockChainHeaders = blockchainHeaders;
|
||||||
|
if (blockChainHeaders.download_progress < 100) {
|
||||||
|
this.setState({
|
||||||
|
message: __('Blockchain Sync'),
|
||||||
|
details: `${__('Catching up with the blockchain')} (${
|
||||||
|
blockchainHeaders.download_progress
|
||||||
|
}%)`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (wallet && wallet.blocks_behind > 0) {
|
||||||
|
const format = wallet.blocks_behind === 1 ? '%s block behind' : '%s blocks behind';
|
||||||
this.setState({
|
this.setState({
|
||||||
message: __('Blockchain Sync'),
|
message: __('Blockchain Sync'),
|
||||||
details: `${__('Catching up with the blockchain')} (${
|
details: __(format, wallet.blocks_behind),
|
||||||
status.blockchain_headers.download_progress
|
|
||||||
}%)`,
|
|
||||||
});
|
});
|
||||||
} else if (status.wallet && status.wallet.blocks_behind > 0) {
|
} else if (wallet && wallet.blocks_behind === 0) {
|
||||||
const format = status.wallet.blocks_behind === 1 ? '%s block behind' : '%s blocks behind';
|
|
||||||
this.setState({
|
|
||||||
message: __('Blockchain Sync'),
|
|
||||||
details: __(format, status.wallet.blocks_behind),
|
|
||||||
});
|
|
||||||
} else if (status.wallet && status.wallet.blocks_behind === 0) {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
message: 'Network Loading',
|
message: 'Network Loading',
|
||||||
details: 'Initializing LBRY service...',
|
details: 'Initializing LBRY service...',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.updateStatus();
|
this.updateStatus();
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasRecordedUser: boolean;
|
hasRecordedUser: boolean;
|
||||||
|
timeout: ?TimeoutID;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { notification } = this.props;
|
const { notification } = this.props;
|
||||||
const { message, details, isRunning } = this.state;
|
const { message, details, isRunning, error } = this.state;
|
||||||
|
|
||||||
const notificationId = notification && notification.id;
|
const notificationId = notification && notification.id;
|
||||||
|
|
||||||
// {notificationId === MODALS.WALLET_UNLOCK && <ModalWalletUnlock />}
|
// {notificationId === MODALS.WALLET_UNLOCK && <ModalWalletUnlock />}
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<LoadScreen message={message} details={details} />
|
<LoadScreen message={message} details={details} error={error} />
|
||||||
{/* Temp hack: don't show any modals on splash screen daemon is running;
|
{/* Temp hack: don't show any modals on splash screen daemon is running;
|
||||||
daemon doesn't let you quit during startup, so the "Quit" buttons
|
daemon doesn't let you quit during startup, so the "Quit" buttons
|
||||||
in the modals won't work. */}
|
in the modals won't work. */}
|
||||||
|
|
|
@ -183,6 +183,16 @@
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.btn--load-screen {
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 1px solid $lbry-white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $lbry-blue-1;
|
||||||
|
border-bottom: 1px solid $lbry-blue-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icon + .btn__label {
|
.icon + .btn__label {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
color: $lbry-white;
|
color: $lbry-white;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.load-screen__header {
|
.load-screen__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-top: 35vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.load-screen__title {
|
.load-screen__title {
|
||||||
|
@ -41,3 +41,8 @@
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
padding-top: $spacing-vertical * 2/3;
|
padding-top: $spacing-vertical * 2/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.load-screen--help {
|
||||||
|
font-size: 14px;
|
||||||
|
padding-top: $spacing-vertical;
|
||||||
|
}
|
||||||
|
|
48
src/renderer/types/status.js
Normal file
48
src/renderer/types/status.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
export type Status = {
|
||||||
|
error?: {},
|
||||||
|
is_running: boolean,
|
||||||
|
is_first_run: boolean,
|
||||||
|
installation_id: string,
|
||||||
|
skipped_components: Array<string>,
|
||||||
|
startup_status: {
|
||||||
|
blob_manager: boolean,
|
||||||
|
blockchain_headers: boolean,
|
||||||
|
database: boolean,
|
||||||
|
dht: boolean,
|
||||||
|
exchange_rate_manager: boolean,
|
||||||
|
file_manager: boolean,
|
||||||
|
hash_announcer: boolean,
|
||||||
|
payment_rate_manager: boolean,
|
||||||
|
peer_protocol_server: boolean,
|
||||||
|
rate_limiter: boolean,
|
||||||
|
stream_identifier: boolean,
|
||||||
|
upnp: boolean,
|
||||||
|
wallet: boolean,
|
||||||
|
},
|
||||||
|
blob_manager: {
|
||||||
|
finished_blobs: number,
|
||||||
|
},
|
||||||
|
connection_status: {
|
||||||
|
code: string,
|
||||||
|
message: string,
|
||||||
|
},
|
||||||
|
dht: {
|
||||||
|
node_id: string,
|
||||||
|
peers_in_routing_table: number,
|
||||||
|
},
|
||||||
|
hash_announcer: {
|
||||||
|
announce_queue_size: number,
|
||||||
|
},
|
||||||
|
wallet?: {
|
||||||
|
best_blockhash: string,
|
||||||
|
blocks: number,
|
||||||
|
blocks_behind: number,
|
||||||
|
is_encrypted: boolean,
|
||||||
|
is_locked: boolean,
|
||||||
|
},
|
||||||
|
blockchain_headers?: {
|
||||||
|
download_progress: number,
|
||||||
|
},
|
||||||
|
};
|
37
yarn.lock
37
yarn.lock
|
@ -2247,7 +2247,7 @@ copy-descriptor@^0.1.0:
|
||||||
|
|
||||||
core-js@^1.0.0:
|
core-js@^1.0.0:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
|
resolved "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
|
||||||
|
|
||||||
core-js@^2.4.0, core-js@^2.5.0:
|
core-js@^2.4.0, core-js@^2.5.0:
|
||||||
version "2.5.7"
|
version "2.5.7"
|
||||||
|
@ -4076,7 +4076,7 @@ flatten@^1.0.2:
|
||||||
|
|
||||||
flow-bin@^0.69.0:
|
flow-bin@^0.69.0:
|
||||||
version "0.69.0"
|
version "0.69.0"
|
||||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.69.0.tgz#053159a684a6051fcbf0b71a2eb19a9679082da6"
|
resolved "http://registry.npmjs.org/flow-bin/-/flow-bin-0.69.0.tgz#053159a684a6051fcbf0b71a2eb19a9679082da6"
|
||||||
|
|
||||||
flow-typed@^2.3.0:
|
flow-typed@^2.3.0:
|
||||||
version "2.5.1"
|
version "2.5.1"
|
||||||
|
@ -4870,12 +4870,18 @@ iconv-lite@0.4.19:
|
||||||
version "0.4.19"
|
version "0.4.19"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
|
||||||
|
|
||||||
iconv-lite@^0.4.17, iconv-lite@^0.4.23, iconv-lite@^0.4.4, iconv-lite@^0.4.5, iconv-lite@~0.4.13:
|
iconv-lite@^0.4.17, iconv-lite@^0.4.23, iconv-lite@^0.4.4, iconv-lite@^0.4.5:
|
||||||
version "0.4.23"
|
version "0.4.23"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3"
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
|
iconv-lite@~0.4.13:
|
||||||
|
version "0.4.24"
|
||||||
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||||
|
dependencies:
|
||||||
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
icss-replace-symbols@^1.1.0:
|
icss-replace-symbols@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
|
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
|
||||||
|
@ -7899,13 +7905,13 @@ react@^0.14.5:
|
||||||
fbjs "^0.6.1"
|
fbjs "^0.6.1"
|
||||||
|
|
||||||
react@^16.3.0:
|
react@^16.3.0:
|
||||||
version "16.4.1"
|
version "16.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32"
|
resolved "https://registry.yarnpkg.com/react/-/react-16.6.1.tgz#ee2aef4f0a09e494594882029821049772f915fe"
|
||||||
dependencies:
|
dependencies:
|
||||||
fbjs "^0.8.16"
|
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
prop-types "^15.6.0"
|
prop-types "^15.6.2"
|
||||||
|
scheduler "^0.11.0"
|
||||||
|
|
||||||
read-config-file@3.1.0, read-config-file@^3.0.0:
|
read-config-file@3.1.0, read-config-file@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
|
@ -8498,6 +8504,13 @@ sax@~1.1.1:
|
||||||
version "1.1.6"
|
version "1.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240"
|
resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240"
|
||||||
|
|
||||||
|
scheduler@^0.11.0:
|
||||||
|
version "0.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.0.tgz#def1f1bfa6550cc57981a87106e65e8aea41a6b5"
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
object-assign "^4.1.1"
|
||||||
|
|
||||||
schema-utils@^0.3.0:
|
schema-utils@^0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"
|
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"
|
||||||
|
@ -9561,7 +9574,11 @@ typo-js@*:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.0.3.tgz#54d8ebc7949f1a7810908b6002c6841526c99d5a"
|
resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.0.3.tgz#54d8ebc7949f1a7810908b6002c6841526c99d5a"
|
||||||
|
|
||||||
ua-parser-js@^0.7.18, ua-parser-js@^0.7.9:
|
ua-parser-js@^0.7.18:
|
||||||
|
version "0.7.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b"
|
||||||
|
|
||||||
|
ua-parser-js@^0.7.9:
|
||||||
version "0.7.18"
|
version "0.7.18"
|
||||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed"
|
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed"
|
||||||
|
|
||||||
|
@ -10146,8 +10163,8 @@ websocket-extensions@>=0.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
|
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
|
||||||
|
|
||||||
whatwg-fetch@>=0.10.0:
|
whatwg-fetch@>=0.10.0:
|
||||||
version "2.0.4"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
|
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
|
||||||
|
|
||||||
whatwg-fetch@^0.9.0:
|
whatwg-fetch@^0.9.0:
|
||||||
version "0.9.0"
|
version "0.9.0"
|
||||||
|
|
Loading…
Reference in a new issue