Upgrade to intl@^3.0.0

This commit is contained in:
SleepWalker 2019-11-11 10:40:05 +02:00
parent 705bc2f9d6
commit 2708650f17
21 changed files with 500 additions and 203 deletions

View File

@ -17,3 +17,4 @@ module.file_ext=.jsx
module.file_ext=.css
module.file_ext=.scss
module.ignore_non_literal_requires=true
esproposal.optional_chaining=enable

View File

@ -4,6 +4,8 @@ module.exports = {
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-function-bind',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-proposal-nullish-coalescing-operator',
[
'@babel/plugin-transform-runtime',
{

View File

@ -42,7 +42,9 @@ declare module "react-intl" {
declare type $npm$ReactIntl$IntlFormat = {
formatDate: (value: any, options?: Object) => string,
formatTime: (value: any, options?: Object) => string,
formatRelative: (value: any, options?: Object) => string,
formatRelativeTime: (value: number, options?: $npm$ReactIntl$RelativeFormatOptions & {
format: string
}) => string,
formatNumber: (value: any, options?: Object) => string,
formatPlural: (value: any, options?: Object) => string,
formatMessage: (
@ -77,8 +79,9 @@ declare module "react-intl" {
};
declare type $npm$ReactIntl$RelativeFormatOptions = {
style?: "best fit" | "numeric",
units?: "second" | "minute" | "hour" | "day" | "month" | "year"
numeric?: "auto" | "always",
style?: "short" | "narrow" | "numeric",
unit?: "second" | "minute" | "hour" | "day" | "month" | "year"
};
declare type $npm$ReactIntl$NumberFormatOptions = {
@ -161,6 +164,15 @@ declare module "react-intl" {
$Diff<React$ElementConfig<Component>, InjectIntlVoidProps>
>;
declare type IntlCache = any;
declare function createIntlCache(): IntlCache;
declare function createIntl(options: {
locale: string,
messages?: {[key: string]: string}
}, cache?: IntlCache): IntlShape;
declare function formatMessage(
messageDescriptor: $npm$ReactIntl$MessageDescriptor,
values?: Object
@ -177,11 +189,10 @@ declare module "react-intl" {
value: any,
options?: $npm$ReactIntl$DateTimeFormatOptions & { format: string }
): string;
declare function formatRelative(
value: any,
declare function formatRelativeTime(
value: number, // delta
options?: $npm$ReactIntl$RelativeFormatOptions & {
format: string,
now: any
format: string
}
): string;
declare function formatNumber(
@ -223,12 +234,11 @@ declare module "react-intl" {
children?: (formattedDate: string) => React$Node
}
> {}
declare class FormattedRelative extends React$Component<
declare class FormattedRelativeTime extends React$Component<
$npm$ReactIntl$RelativeFormatOptions & {
value: $npm$ReactIntl$DateParseable,
value: number, // delta
format?: string,
updateInterval?: number,
initialNow?: $npm$ReactIntl$DateParseable,
updateIntervalInSeconds?: number,
children?: (formattedDate: string) => React$Node
}
> {}
@ -257,6 +267,12 @@ declare module "react-intl" {
initialNow?: $npm$ReactIntl$DateParseable
}
> {}
declare class RawIntlProvider extends React$Component<
{|
children?: React$Node,
value?: IntlShape
|}
> {}
declare type IntlShape = $npm$ReactIntl$IntlShape;
declare type MessageDescriptor = $npm$ReactIntl$MessageDescriptor;
}

View File

@ -39,9 +39,12 @@
"build:install": "yarn install",
"build:webpack": "NODE_PATH=./src webpack --colors -p --bail",
"build:quiet": "yarn run clean && yarn run build:webpack --quiet",
"build:dll": "node ./scripts/build-dll.js"
"build:dll": "node ./scripts/build-dll.js",
"build:serve": "http-server --proxy https://dev.account.ely.by ./dist"
},
"dependencies": {
"@formatjs/intl-pluralrules": "^1.3.2",
"@formatjs/intl-relativetimeformat": "^4.4.1",
"@hot-loader/react-dom": "^16.11.0",
"classnames": "^2.2.6",
"copy-to-clipboard": "^3.0.8",
@ -56,7 +59,7 @@
"react-dom": "^16.11.0",
"react-helmet": "^5.0.0",
"react-hot-loader": "^4.12.16",
"react-intl": "^2.7.2",
"react-intl": "^3.4.0",
"react-motion": "^0.5.0",
"react-redux": "^7.1.3",
"react-router-dom": "^5.1.2",
@ -82,7 +85,7 @@
"@babel/plugin-proposal-function-sent": "^7.7.0",
"@babel/plugin-proposal-json-strings": "^7.0.0",
"@babel/plugin-proposal-logical-assignment-operators": "^7.0.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
"@babel/plugin-proposal-numeric-separator": "^7.0.0",
"@babel/plugin-proposal-optional-chaining": "^7.6.0",
"@babel/plugin-proposal-pipeline-operator": "^7.5.0",
@ -96,7 +99,7 @@
"@babel/runtime-corejs3": "^7.7.2",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.0",
"babel-plugin-react-intl": "^2.0.0",
"babel-plugin-react-intl": "^5.1.1",
"core-js": "3.4.0",
"csp-webpack-plugin": "^2.0.2",
"css-loader": "^3.2.0",

View File

@ -1,24 +1,32 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
// @flow
import type { Node } from 'react';
import type { IntlShape } from 'react-intl';
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { RawIntlProvider } from 'react-intl';
import i18n from 'services/i18n';
import { IntlProvider as OrigIntlProvider } from 'react-intl';
type OwnProps = {|
children: Node
|};
class IntlProvider extends Component {
static displayName = 'IntlProvider';
static propTypes = {
locale: PropTypes.string,
messages: PropTypes.objectOf(PropTypes.string),
children: PropTypes.element
};
type Props = {
...OwnProps,
locale: string
};
render() {
return (
<OrigIntlProvider locale="en" {...this.props} />
);
}
function IntlProvider({ children, locale }: Props) {
const [intl, setIntl] = useState<IntlShape>(i18n.getIntl());
useEffect(() => {
(async () => {
setIntl(await i18n.changeLocale(locale));
})();
}, [locale]);
return <RawIntlProvider value={intl}>{children}</RawIntlProvider>;
}
import { connect } from 'react-redux';
export default connect(({i18n}) => i18n)(IntlProvider);
export default connect<Props, OwnProps, _, _, _, _>(({ i18n }) => i18n)(
IntlProvider
);

View File

@ -1,26 +1,22 @@
// @flow
import i18n from 'services/i18n';
import captcha from 'services/captcha';
export const SET_LOCALE = 'i18n:setLocale';
export function setLocale(desiredLocale: string) {
return async (dispatch: (action: Object) => any) => {
const { locale, messages } = await i18n.require(i18n.detectLanguage(desiredLocale));
dispatch(_setLocale(locale, messages));
return async (dispatch: (action: Object) => any): Promise<string> => {
const locale = i18n.detectLanguage(desiredLocale);
// TODO: probably should be moved from here, because it is a side effect
captcha.setLang(locale);
dispatch(_setLocale(locale));
return locale;
};
}
function _setLocale(locale: string, messages: { [string]: string }) {
function _setLocale(locale: string) {
return {
type: SET_LOCALE,
payload: {
locale,
messages,
},
};
}

View File

@ -1,6 +1,18 @@
// @flow
import i18n from 'services/i18n';
import { SET_LOCALE } from './actions';
export default function(state = {}, {type, payload}) {
type State = { locale: string };
const defaultState = {
locale: i18n.detectLanguage()
};
export default function(
state: State = defaultState,
{ type, payload }: { type: string, payload: State }
): State {
if (type === SET_LOCALE) {
return payload;
}

View File

@ -1,6 +1,7 @@
// @flow
import type { IntlShape } from 'react-intl';
import React, { Component } from 'react';
import { FormattedMessage as Message, intlShape } from 'react-intl';
import { FormattedMessage as Message, injectIntl } from 'react-intl';
import classNames from 'classnames';
import { connect } from 'react-redux';
import { changeLang } from 'components/user/actions';
@ -36,6 +37,7 @@ type OwnProps = {|
type Props = {
...OwnProps,
intl: IntlShape,
selectedLocale: string,
changeLang: (lang: string) => void,
};
@ -44,10 +46,6 @@ class LanguageSwitcher extends Component<Props, {
filter: string,
filteredLangs: LocalesMap,
}> {
static contextTypes = {
intl: intlShape,
};
state = {
filter: '',
filteredLangs: this.props.langs,
@ -59,7 +57,7 @@ class LanguageSwitcher extends Component<Props, {
};
render() {
const { selectedLocale, onClose } = this.props;
const { selectedLocale, onClose, intl } = this.props;
const { filteredLangs } = this.state;
return (
@ -79,7 +77,7 @@ class LanguageSwitcher extends Component<Props, {
formStyles.lightTextField,
formStyles.greenTextField,
)}
placeholder={this.context.intl.formatMessage(messages.startTyping)}
placeholder={intl.formatMessage(messages.startTyping)}
onChange={this.onFilterUpdate}
onKeyPress={this.onFilterKeyPress()}
autoFocus
@ -161,8 +159,10 @@ class LanguageSwitcher extends Component<Props, {
}
}
export default connect<Props, OwnProps, _, _, _, _>((state) => ({
selectedLocale: state.i18n.locale,
}), {
changeLang,
})(LanguageSwitcher);
export default injectIntl(
connect<Props, OwnProps, _, _, _, _>((state) => ({
selectedLocale: state.i18n.locale,
}), {
changeLang,
})(LanguageSwitcher)
);

View File

@ -1,10 +1,12 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { FormattedMessage as Message, FormattedRelative as Relative } from 'react-intl';
import { FormattedMessage as Message } from 'react-intl';
import { Link } from 'react-router-dom';
import Helmet from 'react-helmet';
import { ChangeLanguageLink } from 'components/languageSwitcher';
import { RelativeTime } from 'components/ui';
import ProfileField from './ProfileField';
import styles from './profile.scss';
import profileForm from './profileForm.scss';
@ -85,7 +87,7 @@ class Profile extends Component<Props> {
link="/profile/change-password"
label={<Message {...messages.password} />}
value={<Message {...messages.changedAt} values={{
at: (<Relative value={user.passwordChangedAt * 1000} updateInterval={1000} />)
at: (<RelativeTime timestamp={user.passwordChangedAt * 1000} />),
}} />}
/>

View File

@ -0,0 +1,19 @@
// @flow
import React from 'react';
import { FormattedRelativeTime } from 'react-intl';
import { selectUnit } from '@formatjs/intl-utils';
function RelativeTime({timestamp}: {timestamp: number}) {
const {unit, value}: {unit: any, value: number} = selectUnit(timestamp);
return (
<FormattedRelativeTime
value={value}
unit={unit}
numeric="auto"
updateIntervalInSeconds={['seconds', 'minute', 'hour'].includes(unit) ? 1 : undefined}
/>
);
}
export default RelativeTime;

View File

@ -1,13 +1,10 @@
// @flow
import type { MessageDescriptor } from 'react-intl';
import type { Element } from 'react';
import { Component } from 'react';
import { intlShape } from 'react-intl';
export default class FormComponent<P, S = void> extends Component<P, S> {
static contextTypes = {
intl: intlShape,
};
import i18n from 'services/i18n';
class FormComponent<P, S = void> extends Component<P, S> {
/**
* Formats message resolving intl translations
*
@ -15,16 +12,16 @@ export default class FormComponent<P, S = void> extends Component<P, S> {
*
* @return {string}
*/
formatMessage(message: string | MessageDescriptor): string {
if (message && message.id) {
if (this.context && this.context.intl) {
message = this.context.intl.formatMessage(message);
} else {
return '';
}
formatMessage(message: string | MessageDescriptor | Element<any>): string | Element<any> {
if (typeof message === 'string') {
return message;
}
return ((message: any): string);
if (message && message.id) {
return i18n.getIntl().formatMessage(message);
}
return ((message: any): Element<any>);
}
/**
@ -40,3 +37,5 @@ export default class FormComponent<P, S = void> extends Component<P, S> {
onFormInvalid() {
}
}
export default FormComponent;

View File

@ -37,3 +37,5 @@ export const SKIN_DARK: Skin = 'dark';
export const SKIN_LIGHT: Skin = 'light';
export const skins: Array<Skin> = [SKIN_DARK, SKIN_LIGHT];
export {default as RelativeTime} from './RelativeTime';

View File

@ -40,13 +40,16 @@ export function setUser(payload: $Shape<User>) {
export const CHANGE_LANG = 'USER_CHANGE_LANG';
export function changeLang(lang: string) {
return (dispatch: Dispatch, getState: () => State) => dispatch(setLocale(lang))
.then((lang) => {
.then((lang: string) => {
const { id, isGuest, lang: oldLang } = getState().user;
if (oldLang === lang) {
return;
}
!isGuest && changeLangEndpoint(((id: any): number), lang); // hack to tell Flow that it's defined
if (!isGuest && id) {
changeLangEndpoint(id, lang);
}
dispatch({
type: CHANGE_LANG,

View File

@ -11,6 +11,7 @@ import loader from 'services/loader';
import logger from 'services/logger';
import font from 'services/font';
import history, { browserHistory } from 'services/history';
import i18n from 'services/i18n';
import { loadScript, debounce } from 'functions';
import App from './App';
@ -28,7 +29,8 @@ authFlow.setStore(store);
Promise.all([
userFactory(store),
font.load(['Roboto', 'Roboto Condensed'])
font.load(['Roboto', 'Roboto Condensed']),
i18n.ensureIntl(), // ensure, that intl is polyfilled before any rendering
]).then(() => {
ReactDOM.render(
<App store={store} browserHistory={browserHistory} />,

View File

@ -1,6 +1,7 @@
import React from 'react';
import { FormattedMessage as Message, FormattedRelative as Relative } from 'react-intl';
import { FormattedMessage as Message } from 'react-intl';
import { RelativeTime } from 'components/ui';
import { Link } from 'react-router-dom';
import messages from './errorsDict.intl.json';
@ -76,7 +77,7 @@ const errorsMap = {
'error.recently_sent_message': (props) => (
<Message {...messages.emailFrequency} values={{
// for msLeft @see AuthError.jsx
time: <Relative value={props.msLeft} updateInterval={1000} />
time: <RelativeTime value={props.msLeft} />
}} />
),

View File

@ -1,53 +0,0 @@
// @flow
import locales from 'i18n/index.json';
import { addLocaleData } from 'react-intl';
const SUPPORTED_LANGUAGES = Object.keys(locales);
const DEFAULT_LANGUAGE = 'en';
const needPolyfill = !window.Intl;
function getUserLanguages(userSelectedLang: string): Array<string> {
return [userSelectedLang]
.concat(navigator.languages || [])
.concat(navigator.language || []);
}
function detectLanguage(
userLanguages: Array<string>,
availableLanguages: Array<string>,
defaultLanguage: string,
): string {
return userLanguages
.map((lang) => lang.split('-').shift().toLowerCase())
.find((lang) => availableLanguages.indexOf(lang) !== -1) || defaultLanguage;
}
export default {
detectLanguage(lang: string): string {
return detectLanguage(getUserLanguages(lang), SUPPORTED_LANGUAGES, DEFAULT_LANGUAGE);
},
require(locale: string): Promise<{
locale: string;
messages: { [string]: string };
}> {
const promises: Array<Promise<any>> = [
import(/* webpackChunkName: "locale-[request]" */`react-intl/locale-data/${locale}.js`),
import(/* webpackChunkName: "locale-[request]" */`i18n/${locale}.json`),
];
if (needPolyfill) {
promises.push(import(/* webpackChunkName: "intl-polyfill" */'intl'));
promises.push(import(/* webpackChunkName: "intl-polyfill-[request]" */`intl/locale-data/jsonp/${locale}.js`));
}
return Promise.all(promises)
.then(([localeData, {default: messages}]) => {
addLocaleData(localeData);
return {locale, messages};
});
}
};

85
src/services/i18n/i18n.js Normal file
View File

@ -0,0 +1,85 @@
// @flow
import type {IntlShape} from 'react-intl';
import {createIntl, createIntlCache} from 'react-intl';
import captcha from 'services/captcha';
import locales from 'i18n/index.json';
import intlPolyfill from './intlPolyfill';
const SUPPORTED_LANGUAGES = Object.keys(locales);
const DEFAULT_LANGUAGE = 'en';
function getBrowserPreferredLanguages(): string[] {
return []
.concat(navigator.languages || [])
.concat(navigator.language || []);
}
function detectLanguage(
userLanguages: string[],
availableLanguages: string[],
defaultLanguage: string,
): string {
return userLanguages
.map((lang) => lang.split('-').shift().toLowerCase())
.find((lang) => availableLanguages.indexOf(lang) !== -1) || defaultLanguage;
}
const cache = createIntlCache();
let intl: IntlShape;
class I18N {
detectLanguage(lang: string): string {
return detectLanguage(
[lang].concat(getBrowserPreferredLanguages()).filter((item) => !!item),
SUPPORTED_LANGUAGES,
DEFAULT_LANGUAGE
);
}
getIntl(): IntlShape {
if (!intl) {
intl = createIntl({
locale: 'en',
messages: {}
}, cache);
}
return intl;
}
async changeLocale(locale: string = DEFAULT_LANGUAGE): Promise<IntlShape> {
const { messages } = await this.require(locale);
captcha.setLang(locale);
intl = createIntl({
locale,
messages
}, cache);
return intl;
}
async ensureIntl() {
await intlPolyfill('en');
}
async require(locale: string): Promise<{
locale: string;
messages: { [string]: string };
}> {
const [{default: messages}] = await Promise.all([
import(/* webpackChunkName: "locale-[request]" */`i18n/${locale}.json`),
intlPolyfill(locale)
]);
return {
locale,
messages
};
}
}
export default new I18N();

View File

@ -0,0 +1,2 @@
// @flow
export { default } from './i18n';

View File

@ -0,0 +1,100 @@
// @flow
import logger from 'services/logger';
const needs = {
intl: !window.Intl,
plural: !window?.Intl?.PluralRules,
relative: !window?.Intl?.RelativeTimeFormat
};
/**
* All modern browsers currently do support all required Intl APIs,
* for the outdated browsers we will polyfill this api on demand
*/
async function polyfill(locale: string): Promise<void> {
const promises = [];
if (!needs.intl
&& Intl.DateTimeFormat.supportedLocalesOf([locale]).length === 0
) {
// fallback to polyfill in case, when browser does not support locale we need
needs.intl = true;
needs.plural = true;
needs.relative = true;
}
if (needs.intl) {
promises.push(polyfillIntl(locale));
} else {
if (needs.plural) {
promises.push(polyfillPlural(locale));
}
if (needs.relative) {
promises.push(polyfillRelative(locale));
}
}
try {
await Promise.all(promises);
} catch (error) {
logger.warn('Error loading intl polyfills', {
error
});
}
}
async function polyfillIntl(locale: string): Promise<void> {
// do not rely on tests provided by polyfill implementation
// forcibly apply polyfill, because if this function was called
// this means that browser does not support some of locales
const {default: Intl} = await import(
/* webpackChunkName: "intl" */
'intl'
);
window.Intl = Intl;
// MUST be loaded in series with the main polyfill
await Promise.all([
import(
// WARNING: .js extension is required for proper function of ContextReplacementPlugin
/* webpackChunkName: "intl-[request]" */
`intl/locale-data/jsonp/${locale}.js`
),
polyfillPlural(locale),
polyfillRelative(locale),
]);
}
async function polyfillPlural(locale: string): Promise<void> {
await import(
/* webpackChunkName: "intl-pluralrules" */
'@formatjs/intl-pluralrules/polyfill'
);
// MUST be loaded in series with the main polyfill
await import(
// WARNING: .js extension is required for proper function of ContextReplacementPlugin
/* webpackChunkName: "intl-pluralrules-[request]" */
`@formatjs/intl-pluralrules/dist/locale-data/${locale}.js`
);
}
async function polyfillRelative(locale: string): Promise<void> {
await import(
/* webpackChunkName: "intl-relativetimeformat" */
'@formatjs/intl-relativetimeformat/polyfill'
);
// MUST be loaded in series with the main polyfill
await import(
// WARNING: .js extension is required for proper function of ContextReplacementPlugin
/* webpackChunkName: "intl-relativetimeformat-[request]" */
`@formatjs/intl-relativetimeformat/dist/locale-data/${locale}.js`
);
}
export default polyfill;

View File

@ -57,7 +57,7 @@ const webpackConfig = {
modules: [rootPath, 'node_modules'],
extensions: ['.js', '.jsx', '.json'],
alias: {
'react-dom': '@hot-loader/react-dom'
'react-dom': isProduction ? 'react-dom' : '@hot-loader/react-dom'
}
},
@ -137,10 +137,10 @@ const webpackConfig = {
}
),
// restrict webpack import context, to create chunks only for supported locales
// @see services/i18n.js
// @see services/i18n/intlPolyfill.js
new webpack.ContextReplacementPlugin(
/locale-data/,
new RegExp(`/(${SUPPORTED_LANGUAGES.join('|')})\\.js`)
new RegExp(`/(${SUPPORTED_LANGUAGES.join('|')})\\.js$`)
),
// @see components/i18n/localeFlags.js
new webpack.ContextReplacementPlugin(
@ -264,7 +264,10 @@ if (isProduction) {
splitChunks: {
cacheGroups: {
vendor: {
test: (m) => String(m.context).includes('node_modules') && !String(m.context).includes('flag-icon-css'),
test: (m) => String(m.context).includes('node_modules')
// icons and intl with relateed polyfills are allowed
// to be splitted to other chunks
&& !/\/(flag-icon-css|intl|@formatjs)\//.test(String(m.context)),
name: 'vendors',
chunks: 'all',
},

234
yarn.lock
View File

@ -32,7 +32,7 @@
dependencies:
"@babel/highlight" "^7.0.0"
"@babel/core@^7.7.2":
"@babel/core@^7.6.2", "@babel/core@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.2.tgz#ea5b99693bcfc058116f42fa1dd54da412b29d91"
integrity sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==
@ -374,16 +374,16 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.2.3.tgz#32f5df65744b70888d17872ec106b02434ba1489"
integrity sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==
"@babel/parser@^7.1.0", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2":
version "7.7.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043"
integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==
"@babel/parser@^7.4.4", "@babel/parser@^7.4.5":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872"
integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==
"@babel/parser@^7.7.0", "@babel/parser@^7.7.2":
version "7.7.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043"
integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==
"@babel/plugin-proposal-async-generator-functions@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz#83ef2d6044496b4c15d8b4904e2219e6dccc6971"
@ -475,7 +475,7 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-logical-assignment-operators" "^7.2.0"
"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0":
"@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.4.4.tgz#41c360d59481d88e0ce3a3f837df10121a769b39"
integrity sha512-Amph7Epui1Dh/xxUxS2+K22/MUi6+6JVTvy3P58tja3B6yKTSjwwx0/d83rF7551D6PVSSoplQb8GCwqec7HRw==
@ -1177,6 +1177,15 @@
lodash "^4.17.10"
to-fast-properties "^2.0.0"
"@babel/types@^7.3.0", "@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7"
integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==
dependencies:
esutils "^2.0.2"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@babel/types@^7.4.4":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0"
@ -1186,15 +1195,6 @@
lodash "^4.17.11"
to-fast-properties "^2.0.0"
"@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7"
integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==
dependencies:
esutils "^2.0.2"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@cypress/listr-verbose-renderer@0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a"
@ -1213,6 +1213,39 @@
debug "^3.1.0"
lodash.once "^4.1.1"
"@formatjs/intl-pluralrules@^1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-1.3.2.tgz#10b4d09526739d2146ef5e05c8540db3343862c7"
integrity sha512-ZPHR7c4dEQ+7Y2pav2p55xfB8fbNMdr8iUqiH+T1FcXWDBE3ISlp/qU0fii97P4Co4dRXA6LCpfcdVcfQzzSmw==
dependencies:
"@formatjs/intl-utils" "^1.4.0"
"@formatjs/intl-relativetimeformat@^4.2.1":
version "4.4.0"
resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-4.4.0.tgz#8de1d25457cd34531c87f3fa4c7d381606f010ed"
integrity sha512-8lXOWWvoIPJR8Ak1uywE/gajBmHppfIg6a1o/fyd3t6NV7Qe+PVj7SJ5SgyRUcK3xQVA6AXpDJ7LCyjo5iOD8g==
dependencies:
"@formatjs/intl-utils" "^1.4.0"
"@formatjs/intl-relativetimeformat@^4.4.1":
version "4.4.1"
resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-4.4.1.tgz#2277daba93462781d126abfe071f3aa66c247a19"
integrity sha512-VOc/uvZy1qmw7ssBMumNdinDg3Hvzbvmiqaaz8SMr+znYXd1D6Ogd2JsaskSrr3/bJOscEN5W4wNHFl1McfffQ==
dependencies:
"@formatjs/intl-utils" "^1.4.0"
"@formatjs/intl-unified-numberformat@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@formatjs/intl-unified-numberformat/-/intl-unified-numberformat-2.1.0.tgz#0b8ef3bc3ebbafb40a65f09606a3fc414f1a392a"
integrity sha512-0zL5DKRe4KiaupyiwT8ckTmE1aPlb2fsR0deMGN4QVlkdCxsCDMrLykrLyrhBa9fthTDaGR4Qh+bALk/sa4Vcg==
dependencies:
"@formatjs/intl-utils" "^1.4.0"
"@formatjs/intl-utils@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@formatjs/intl-utils/-/intl-utils-1.4.0.tgz#b59fdf78bbae9f99c500a298bf73b1945f5991f1"
integrity sha512-z5HyJumGzORM+5SpvkAlp/hu0AHDeZcUNKSmj9NjS7kWxOGZMuAdS3X1K5XiE0j5I8r8s8SIaz0IQOdMA1WFeA==
"@hot-loader/react-dom@^16.11.0":
version "16.11.0"
resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.11.0.tgz#c0b483923b289db5431516f56ee2a69448ebf9bd"
@ -1268,6 +1301,39 @@
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
"@types/babel__core@^7.1.2":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30"
integrity sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==
dependencies:
"@babel/parser" "^7.1.0"
"@babel/types" "^7.0.0"
"@types/babel__generator" "*"
"@types/babel__template" "*"
"@types/babel__traverse" "*"
"@types/babel__generator@*":
version "7.6.0"
resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.0.tgz#f1ec1c104d1bb463556ecb724018ab788d0c172a"
integrity sha512-c1mZUu4up5cp9KROs/QAw0gTeHrw/x7m52LcnvMxxOZ03DmLwPV0MlGmlgzV3cnSdjhJOZsj7E7FHeioai+egw==
dependencies:
"@babel/types" "^7.0.0"
"@types/babel__template@*":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307"
integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==
dependencies:
"@babel/parser" "^7.1.0"
"@babel/types" "^7.0.0"
"@types/babel__traverse@*":
version "7.0.7"
resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.7.tgz#2496e9ff56196cc1429c72034e07eab6121b6f3f"
integrity sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==
dependencies:
"@babel/types" "^7.3.0"
"@types/events@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
@ -1282,6 +1348,19 @@
"@types/minimatch" "*"
"@types/node" "*"
"@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/invariant@^2.2.30":
version "2.2.30"
resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.30.tgz#20efa342807606ada5483731a8137cb1561e5fe9"
integrity sha512-98fB+yo7imSD2F7PF7GIpELNgtLNgo5wjivu0W5V4jx+KVVJxo6p/qN4zdzSTBWy4/sN3pPyXwnhRSD28QX+ag==
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@ -1302,7 +1381,7 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
"@types/react@^15.0.0 || ^16.0.0":
"@types/react@*", "@types/react@^15.0.0 || ^16.0.0":
version "16.9.11"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.11.tgz#70e0b7ad79058a7842f25ccf2999807076ada120"
integrity sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ==
@ -1310,6 +1389,11 @@
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/schema-utils@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/schema-utils/-/schema-utils-1.0.0.tgz#295d36f01e2cb8bc3207ca1d9a68e210db6b40cb"
integrity sha512-YesPanU1+WCigC/Aj1Mga8UCOjHIfMNHZ3zzDsUY7lI8GlKnh/Kv2QwJOQ+jNQ36Ru7IfzSedlG14hppYaN13A==
"@types/sizzle@2.3.2":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
@ -1982,22 +2066,18 @@ babel-plugin-dynamic-import-node@^2.3.0:
dependencies:
object.assign "^4.1.0"
babel-plugin-react-intl@^2.0.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-2.4.0.tgz#292fca8030603a9e0476973290836aa0c7da17e2"
integrity sha512-r67nOQdpKxPtDFiJHquTt9dBG0xOlBk1u3rForULNrDXvTzg5RRHbB7RLqqMWOvqfP2znTo0C+e/PLnPKt+JXA==
babel-plugin-react-intl@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-5.1.1.tgz#3c3d8af13aeb7b50c6470fc3d7abe9bdbae9f6da"
integrity sha512-kkghFOjjssYRiVPxwV/6q4WFhpkYw2LnpQAuvqHHDvPbOH2bcAz2U+GXy+W7pzSwH2FPnqegCbzJ4nPogVRGwg==
dependencies:
babel-runtime "^6.2.0"
intl-messageformat-parser "^1.2.0"
mkdirp "^0.5.1"
babel-runtime@^6.2.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
"@babel/core" "^7.6.2"
"@babel/helper-plugin-utils" "^7.0.0"
"@types/babel__core" "^7.1.2"
"@types/schema-utils" "^1.0.0"
fs-extra "^8.0.1"
intl-messageformat-parser "^3.2.2"
schema-utils "^2.2.0"
backo2@1.0.2:
version "1.0.2"
@ -3030,11 +3110,6 @@ core-js@^1.0.0:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
core-js@^2.4.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@ -4781,6 +4856,15 @@ fs-extra@^7.0.1:
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-extra@^8.0.1:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-minipass@^1.2.5:
version "1.2.6"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07"
@ -5086,6 +5170,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
graceful-fs@^4.2.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
greedy-interval-packer@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/greedy-interval-packer/-/greedy-interval-packer-1.2.0.tgz#d6da11f3661bb797812da78a1ea510678a2a8739"
@ -5685,29 +5774,28 @@ interpret@1.2.0:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
intl-format-cache@^2.0.5:
version "2.2.9"
resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-2.2.9.tgz#fb560de20c549cda20b569cf1ffb6dc62b5b93b4"
integrity sha512-Zv/u8wRpekckv0cLkwpVdABYST4hZNTDaX7reFetrYTJwxExR2VyTqQm+l0WmL0Qo8Mjb9Tf33qnfj0T7pjxdQ==
intl-format-cache@^4.2.3, intl-format-cache@^4.2.5:
version "4.2.5"
resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-4.2.5.tgz#6319f5707cdc766ab5c196990a6e55b0df9cc70f"
integrity sha512-xvvog/4HTVhJIg5dexcs6Ji/ROlolCgtz3std23bLEmucoGPrUVrYQPTcBWR314NM9khm4JSrdOamv9SEtvCUg==
intl-messageformat-parser@1.4.0, intl-messageformat-parser@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz#b43d45a97468cadbe44331d74bb1e8dea44fc075"
integrity sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU=
intl-locales-supported@^1.6.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/intl-locales-supported/-/intl-locales-supported-1.8.0.tgz#cfec56f5ac8cbb828bd5ce3155c4392555cd5c5c"
integrity sha512-y1K5NaNM/WjwZcRy4TtRZ4kR8TCXfoPlX2MFbFGWqqYBD0jPG8liX/cU8aBzk2j5+bu1W6ztlLtOfCPAEwQc3A==
intl-messageformat@^2.0.0, intl-messageformat@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-2.2.0.tgz#345bcd46de630b7683330c2e52177ff5eab484fc"
integrity sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw=
intl-messageformat-parser@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-3.2.2.tgz#28cacc80a53823a28b5ecaf16b3b35d0a1d5f9d2"
integrity sha512-ax9639ST77YimAddTH/0Q9qhXuYS8ZVsoqOZinqnS90MbXaNuIq+KIdifaIndwI+lMEv3o+qNaGycXYvlh17rw==
intl-messageformat@^7.3.3:
version "7.5.0"
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-7.5.0.tgz#53582b6e911d4f41434e9d897b4789d2a2b2ff8e"
integrity sha512-s08OFUbRVUPTiXS8OOP06OhfehM1K4ughymhOazY4OhQMO+RiY4bnmsqRgYe7XorETg7mZnwJX1M34sJrzKoOA==
dependencies:
intl-messageformat-parser "1.4.0"
intl-relativeformat@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/intl-relativeformat/-/intl-relativeformat-2.2.0.tgz#6aca95d019ec8d30b6c5653b6629f9983ea5b6c5"
integrity sha512-4bV/7kSKaPEmu6ArxXf9xjv1ny74Zkwuey8Pm01NH4zggPP7JHwg2STk8Y3JdspCKRDriwIyLRfEXnj2ZLr4Bw==
dependencies:
intl-messageformat "^2.0.0"
intl-format-cache "^4.2.5"
intl-messageformat-parser "^3.2.2"
intl@^1.2.5:
version "1.2.5"
@ -8787,16 +8875,22 @@ react-hot-loader@^4.12.16:
shallowequal "^1.1.0"
source-map "^0.7.3"
react-intl@^2.7.2:
version "2.9.0"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-2.9.0.tgz#c97c5d17d4718f1575fdbd5a769f96018a3b1843"
integrity sha512-27jnDlb/d2A7mSJwrbOBnUgD+rPep+abmoJE511Tf8BnoONIAUehy/U1zZCHGO17mnOwMWxqN4qC0nW11cD6rA==
react-intl@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-3.4.0.tgz#25986ac75b3c0073c0a7bce31ab2cb1b8bbf421c"
integrity sha512-pW+z0ngVtPzICQeBrvoxk/YOotjFjVMvqxf/q0hjfM4CLvzIWJW/7MQcOz8ujD0Agf146mYOUv0//a9JM4H6Tg==
dependencies:
"@formatjs/intl-relativetimeformat" "^4.2.1"
"@formatjs/intl-unified-numberformat" "^2.1.0"
"@types/hoist-non-react-statics" "^3.3.1"
"@types/invariant" "^2.2.30"
hoist-non-react-statics "^3.3.0"
intl-format-cache "^2.0.5"
intl-messageformat "^2.1.0"
intl-relativeformat "^2.1.0"
intl-format-cache "^4.2.3"
intl-locales-supported "^1.6.0"
intl-messageformat "^7.3.3"
intl-messageformat-parser "^3.2.2"
invariant "^2.1.1"
shallow-equal "^1.1.0"
react-is@^16.10.2, react-is@^16.9.0:
version "16.11.0"
@ -9090,11 +9184,6 @@ regenerate@^1.4.0:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
regenerator-runtime@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
regenerator-runtime@^0.12.0:
version "0.12.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
@ -9511,7 +9600,7 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.1.0, schema-utils@^2.4.1:
schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.1.0, schema-utils@^2.2.0, schema-utils@^2.4.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.5.0.tgz#8f254f618d402cc80257486213c8970edfd7c22f"
integrity sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==
@ -9656,6 +9745,11 @@ shallow-clone@^3.0.0:
dependencies:
kind-of "^6.0.2"
shallow-equal@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.0.tgz#fd828d2029ff4e19569db7e19e535e94e2d1f5cc"
integrity sha512-Z21pVxR4cXsfwpMKMhCEIO1PCi5sp7KEp+CmOpBQ+E8GpHwKOw2sEzk7sgblM3d/j4z4gakoWEoPcjK0VJQogA==
shallowequal@^1.0.1, shallowequal@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"