begin rework of notifications

The notification reducer should decide when to display notifications rather than having notifications scattered throughout the code.

Also start using translations so that user-visible strings are not scattered in code.
This commit is contained in:
David Lechner
2020-05-26 21:20:08 -05:00
committed by David Lechner
parent ec05ad38aa
commit c373b3abc5
19 changed files with 575 additions and 128 deletions
+5 -1
View File
@@ -3,7 +3,11 @@
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"mrmlnc.vscode-json5"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": []
}
+1
View File
@@ -5,6 +5,7 @@
"dependencies": {
"@pybricks/firmware": "^1.0.0",
"@pybricks/mpy-cross-v4": "^1.0.0",
"@shopify/react-i18n": "^3.0.2",
"@testing-library/jest-dom": "^5.8.0",
"@testing-library/react": "^10.0.4",
"@testing-library/user-event": "^10.3.4",
+27 -8
View File
@@ -18,9 +18,9 @@ export enum BootloaderConnectionActionType {
*/
DidConnect = 'bootloader.action.connection.did.connect',
/**
* The connection was cancelled.
* The connection was not successful.
*/
DidCancel = 'bootloader.action.connection.did.cancel',
DidFailToConnect = 'bootloader.action.connection.did.connect.fail',
/**
* There was a connection error.
*/
@@ -62,12 +62,31 @@ export function didConnect(
return { type: BootloaderConnectionActionType.DidConnect, canWriteWithoutResponse };
}
export type BootloaderConnectionDidCancelAction = Action<
BootloaderConnectionActionType.DidCancel
>;
/**
* Possible reasons a device could fail to connect.
*/
export enum BootloaderConnectionFailureReason {
/** The reason is not known */
Unknown = 'unknown',
/** The connection was canceled */
Canceled = 'canceled',
/** Web Bluetooth is not available */
NoWebBluetooth = 'no-web-bluetooth',
/** Connected but failed to find the bootloader GATT service */
GattServiceNotFound = 'gatt-service-not-found',
}
export function didCancel(): BootloaderConnectionDidCancelAction {
return { type: BootloaderConnectionActionType.DidCancel };
export interface BootloaderConnectionDidFailToConnectAction
extends Action<BootloaderConnectionActionType.DidFailToConnect> {
reason: BootloaderConnectionFailureReason;
err?: Error;
}
export function didFailToConnect(
reason: BootloaderConnectionFailureReason,
err?: Error,
): BootloaderConnectionDidFailToConnectAction {
return { type: BootloaderConnectionActionType.DidFailToConnect, reason, err };
}
export interface BootloaderConnectionDidErrorAction
@@ -124,7 +143,7 @@ export function didDisconnect(): BootloaderConnectionDidDisconnectAction {
export type BootloaderConnectionAction =
| BootloaderConnectionConnectAction
| BootloaderConnectionDidConnectAction
| BootloaderConnectionDidCancelAction
| BootloaderConnectionDidFailToConnectAction
| BootloaderConnectionDidErrorAction
| BootloaderConnectionSendAction
| BootloaderConnectionDidSendAction
+2
View File
@@ -8,6 +8,7 @@ import {
} from './bootloader';
import { EditorAction } from './editor';
import { NotificationAction } from './notification';
import { ServiceWorkerAction } from './service-worker';
import { TerminalDataAction } from './terminal';
/**
@@ -21,6 +22,7 @@ export type Action =
| BootloaderAction
| EditorAction
| NotificationAction
| ServiceWorkerAction
| TerminalDataAction;
/**
+1 -1
View File
@@ -59,7 +59,7 @@ export function add(
message: string,
helpUrl?: string,
): NotificationAddAction {
return { type: NotificationActionType.Add, id: nextId(), level, message, helpUrl };
return { type: NotificationActionType.Add, id: -nextId(), level, message, helpUrl };
}
/**
+27
View File
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020 The Pybricks Authors
import { Action } from 'redux';
export enum ServiceWorkerActionType {
Update = 'serviceWorker.update',
Success = 'serviceWorker.success',
}
export interface ServiceWorkerAction<
T extends ServiceWorkerActionType = ServiceWorkerActionType
> extends Action<T> {
registration: ServiceWorkerRegistration;
}
export function update(
registration: ServiceWorkerRegistration,
): ServiceWorkerAction<ServiceWorkerActionType.Update> {
return { type: ServiceWorkerActionType.Update, registration };
}
export function success(
registration: ServiceWorkerRegistration,
): ServiceWorkerAction<ServiceWorkerActionType.Success> {
return { type: ServiceWorkerActionType.Success, registration };
}
+22 -6
View File
@@ -1,11 +1,13 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020 The Pybricks Authors
import { WithI18nProps, withI18n } from '@shopify/react-i18n';
import React from 'react';
import Toast from 'react-bootstrap/Toast';
import { connect } from 'react-redux';
import { Dispatch } from '../actions';
import * as notification from '../actions/notification';
import { remove } from '../actions/notification';
import en from './notification.en.json';
interface DispatchProps {
onClose: () => void;
@@ -14,11 +16,12 @@ interface DispatchProps {
interface OwnProps {
id: number;
style: string;
message: string;
message?: string;
messageId?: string;
helpUrl?: string;
}
type NotificationProps = DispatchProps & OwnProps;
type NotificationProps = DispatchProps & OwnProps & WithI18nProps;
function mapTitle(style: string): string {
switch (style) {
@@ -47,7 +50,11 @@ class Notification extends React.Component<NotificationProps> {
</strong>
</Toast.Header>
<Toast.Body>
<p>{this.props.message}</p>
<p>
{this.props.messageId
? this.props.i18n.translate(this.props.messageId)
: this.props.message || 'missing message!'}
</p>
<p>
{this.props.helpUrl && (
<a
@@ -67,8 +74,17 @@ class Notification extends React.Component<NotificationProps> {
const mapDispatchToProps = (dispatch: Dispatch, ownProps: OwnProps): DispatchProps => ({
onClose: (): void => {
dispatch(notification.remove(ownProps.id));
dispatch(remove(ownProps.id));
},
});
export default connect(null, mapDispatchToProps)(Notification);
export default connect(
null,
mapDispatchToProps,
)(
withI18n({
id: 'notification',
fallback: en,
translations: () => ({ en }),
})(Notification),
);
+14 -2
View File
@@ -6,7 +6,7 @@ import { Collapse } from 'react-bootstrap';
import { connect } from 'react-redux';
import { TransitionGroup } from 'react-transition-group';
import { RootState } from '../reducers';
import { NotificationList } from '../reducers/notification';
import { Level, NotificationList } from '../reducers/notification';
import Notification from './Notification';
interface StateProps {
@@ -15,6 +15,17 @@ interface StateProps {
type NotificationStackProps = StateProps;
function mapLevelToStyle(level: Level): string {
switch (level) {
case Level.Error:
return 'danger';
case Level.Warning:
return 'warning';
case Level.Info:
return 'info';
}
}
class NotificationStack extends React.Component<NotificationStackProps> {
render(): JSX.Element {
return (
@@ -33,8 +44,9 @@ class NotificationStack extends React.Component<NotificationStackProps> {
<Collapse key={n.id} in={true}>
<Notification
id={n.id}
style={n.style}
style={mapLevelToStyle(n.level)}
message={n.message}
messageId={n.messageId}
helpUrl={n.helpUrl}
/>
</Collapse>
+18
View File
@@ -0,0 +1,18 @@
{
"bootloader": {
"connection": {
"didConnect": {
"cannotWriteWithoutResponse": "This web browser does not support Web Bluetooth Write Characteristic Without Response. Flashing firmware will take a long time."
},
"didFailToConnect": {
"gattServiceNotFound": "Connected to hub but failed to get LEGO bootloader service. Try removing the \"LEGO Bootloader\" device in your OS Bluetooth settings, then try again.",
"noWebBluetooth": "This web browser does not support Web Bluetooth or it is not enabled.",
"unknown": "Unexpected error while trying to connect. Check console log and report the error."
}
}
},
"serviceWorker": {
"success": "Content is cached for offline use.",
"update": "New content is available and will be used when all tabs for this page are closed.'"
}
}
+13 -15
View File
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020 The Pybricks Authors
import { I18nContext, I18nManager } from '@shopify/react-i18n';
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
@@ -10,7 +11,7 @@ import { createEpicMiddleware } from 'redux-observable';
import createSagaMiddleware from 'redux-saga';
import thunkMiddleware from 'redux-thunk';
import './index.scss';
import * as notification from './actions/notification';
import { success, update } from './actions/service-worker';
import App from './components/App';
import NotificationStack from './components/NotificationStack';
import rootEpic from './epics';
@@ -24,6 +25,11 @@ const epicMiddleware = createEpicMiddleware();
// TODO: add runtime option or filter - logger affects firmware flash performance
const loggerMiddleware = createLogger({ predicate: () => false });
const i18n = new I18nManager({
locale: 'en',
onError: (err): void => console.error(err),
});
const store = createStore(
rootReducer,
applyMiddleware(
@@ -41,8 +47,10 @@ epicMiddleware.run(rootEpic);
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<NotificationStack />
<App />
<I18nContext.Provider value={i18n}>
<NotificationStack />
<App />
</I18nContext.Provider>
</Provider>
</React.StrictMode>,
document.getElementById('root'),
@@ -52,16 +60,6 @@ ReactDOM.render(
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.register({
onUpdate: () => {
store.dispatch(
notification.add(
'info',
'New content is available and will be used when all ' +
'tabs for this page are closed. See https://bit.ly/CRA-PWA.',
),
);
},
onSuccess: () => {
store.dispatch(notification.add('info', 'Content is cached for offline use.'));
},
onUpdate: (r) => store.dispatch(update(r)),
onSuccess: (r) => store.dispatch(success(r)),
});
+5
View File
@@ -1,5 +1,10 @@
/// <reference types="react-scripts" />
declare module '*.json' {
const src: object;
export default src;
}
declare module '*.zip' {
const src: string;
export default src;
+1 -8
View File
@@ -44,15 +44,8 @@ const connection: Reducer<BootloaderConnectionState, Action> = (
case BootloaderRequestActionType.Disconnect:
return BootloaderConnectionState.Disconnecting;
case BootloaderConnectionActionType.DidDisconnect:
case BootloaderConnectionActionType.DidCancel:
case BootloaderConnectionActionType.DidFailToConnect:
return BootloaderConnectionState.Disconnected;
case BootloaderConnectionActionType.DidError:
// Error while connecting means we didn't connect.
if (state === BootloaderConnectionState.Connecting) {
return BootloaderConnectionState.Disconnected;
} else {
return state;
}
default:
return state;
}
+87 -12
View File
@@ -3,35 +3,110 @@
import { Reducer } from 'react';
import { combineReducers } from 'redux';
import { NotificationAction, NotificationActionType } from '../actions/notification';
import { Action } from '../actions';
import {
BootloaderConnectionActionType,
BootloaderConnectionFailureReason,
} from '../actions/bootloader';
import { NotificationActionType } from '../actions/notification';
import { ServiceWorkerActionType } from '../actions/service-worker';
import { createCountFunc } from '../utils/iter';
export type NotificationList = Array<{
/**
* Severity level of notification.
*/
export enum Level {
/**
* This is an error (requires user action to resolve)
*/
Error = 'error',
/**
* This is a warning (user could take action or ignore)
*/
Warning = 'warning',
/**
* This is just FYI (no user action required)
*/
Info = 'info',
}
export interface Notification {
readonly id: number;
readonly style: string;
readonly message: string;
readonly level: Level;
readonly message?: string;
readonly messageId?: string;
readonly helpUrl?: string;
}>;
}
const levelMap = {
error: 'danger',
warning: 'warning',
info: 'info',
};
export type NotificationList = Array<Notification>;
const list: Reducer<NotificationList, NotificationAction> = (state = [], action) => {
const nextId = createCountFunc();
function append(
state: NotificationList,
level: Level,
messageId: string,
helpUrl?: string,
): NotificationList {
return [...state, { id: nextId(), level, messageId, helpUrl }];
}
const list: Reducer<NotificationList, Action> = (state = [], action) => {
switch (action.type) {
case BootloaderConnectionActionType.DidConnect:
if (!action.canWriteWithoutResponse) {
return append(
state,
Level.Warning,
'bootloader.connection.didConnect.cannotWriteWithoutResponse',
'https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md',
);
}
return state;
case BootloaderConnectionActionType.DidFailToConnect:
switch (action.reason) {
case BootloaderConnectionFailureReason.GattServiceNotFound:
return append(
state,
Level.Error,
'bootloader.connection.didFailToConnect.gattServiceNotFound',
);
case BootloaderConnectionFailureReason.NoWebBluetooth:
return append(
state,
Level.Error,
'bootloader.connection.didFailToConnect.noWebBluetooth',
'https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md',
);
case BootloaderConnectionFailureReason.Unknown:
return append(
state,
Level.Error,
'bootloader.connection.didFailToConnect.unknown',
);
}
return state;
case NotificationActionType.Add:
return [
...state,
{
id: action.id,
style: levelMap[action.level],
level: action.level as Level,
message: action.message,
helpUrl: action.helpUrl,
},
];
case NotificationActionType.Remove:
return state.filter((e) => e.id !== action.id);
case ServiceWorkerActionType.Update:
return append(
state,
Level.Info,
'serviceWorker.update',
'https://bit.ly/CRA-PWA',
);
case ServiceWorkerActionType.Success:
return append(state, Level.Info, 'serviceWorker.success');
default:
return state;
}
+7 -15
View File
@@ -22,9 +22,8 @@ import {
BootloaderActionType,
BootloaderChecksumResponseAction,
BootloaderConnectionActionType,
BootloaderConnectionDidCancelAction,
BootloaderConnectionDidConnectAction,
BootloaderConnectionDidErrorAction,
BootloaderConnectionDidFailToConnectAction,
BootloaderConnectionDidReceiveAction,
BootloaderConnectionDidSendAction,
BootloaderDidRequestAction,
@@ -312,24 +311,17 @@ function* flashFirmware(action: BootloaderFlashFirmwareAction): Generator {
}
yield put(connect());
const didConnect = (yield take([
const connectResult = (yield take([
BootloaderConnectionActionType.DidConnect,
BootloaderConnectionActionType.DidCancel,
BootloaderConnectionActionType.DidError,
BootloaderConnectionActionType.DidFailToConnect,
])) as
| BootloaderConnectionDidConnectAction
| BootloaderConnectionDidCancelAction
| BootloaderConnectionDidErrorAction;
| BootloaderConnectionDidFailToConnectAction;
if (didConnect.type === BootloaderConnectionActionType.DidCancel) {
if (connectResult.type === BootloaderConnectionActionType.DidFailToConnect) {
return;
}
if (didConnect.type === BootloaderConnectionActionType.DidError) {
// TODO: proper error handling
throw didConnect.err;
}
yield put(infoRequest());
const info = (yield wait(BootloaderResponseActionType.Info)) as WaitResponse<
BootloaderInfoResponseAction
@@ -373,7 +365,7 @@ function* flashFirmware(action: BootloaderFlashFirmwareAction): Generator {
}
// City hub bootloader is buggy. See note in encodeRequest().
if (info[0].hubType === HubType.CityHub && !didConnect.canWriteWithoutResponse) {
if (info[0].hubType === HubType.CityHub && !connectResult.canWriteWithoutResponse) {
yield put(
notification.add(
'error',
@@ -420,7 +412,7 @@ function* flashFirmware(action: BootloaderFlashFirmwareAction): Generator {
yield put(progress(offset, firmware.length));
if (didConnect.canWriteWithoutResponse) {
if (connectResult.canWriteWithoutResponse) {
// request checksum every 8K to prevent buffer overrun on the hub
// because of sending too much data at once
if (++count % 585 === 0) {
+18 -40
View File
@@ -5,14 +5,13 @@ import { Action, Dispatch } from '../actions';
import {
BootloaderConnectionActionType,
didCancel,
BootloaderConnectionFailureReason as Reason,
didConnect,
didDisconnect,
didError,
didFailToConnect,
didReceive,
didSend,
} from '../actions/bootloader';
import * as notification from '../actions/notification';
import { CharacteristicUUID, ServiceUUID } from '../protocols/bootloader';
import {
PolyfillBluetoothRemoteGATTCharacteristic,
@@ -33,13 +32,7 @@ async function connect(action: Action, dispatch: Dispatch): Promise<void> {
throw Error('already connected');
}
if (navigator.bluetooth === undefined) {
dispatch(
notification.add(
'error',
'This web browser does not support Web Bluetooth or it is not enabled.',
'https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md',
),
);
dispatch(didFailToConnect(Reason.NoWebBluetooth));
return;
}
// TODO: check navigator.bluetooth.getAvailability()
@@ -55,7 +48,7 @@ async function connect(action: Action, dispatch: Dispatch): Promise<void> {
) {
// this error is received if the user clicks the cancel button in
// the bluetooth scan dialog
dispatch(didCancel());
dispatch(didFailToConnect(Reason.Canceled));
return;
}
throw err;
@@ -81,44 +74,29 @@ async function connect(action: Action, dispatch: Dispatch): Promise<void> {
dispatch(didReceive(char.value));
});
await char.startNotifications();
// char.writeValueWithoutResponse() was introduced in Chrome 85
// Older versions of Chrome for Android will write without response
// by default, so don't warn on Android.
if (
!char.writeValueWithoutResponse &&
!/Android/i.test(navigator.userAgent)
) {
// TODO: this needs to be an error if connected to city hub
// however it is not currently possible to get mfg-specific
// advertising data, so we don't know what type of hub it is
// until after we connect
dispatch(
notification.add(
'warning',
'This web browser does not support Web Bluetooth Write Characteristic Without Response. Flashing firmware will take a long time.',
'https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md',
),
);
}
} catch (err) {
device.gatt.disconnect();
if (
err instanceof DOMException &&
err.code === DOMException.NOT_FOUND_ERR
) {
dispatch(
notification.add(
'error',
'Connected to hub but failed to get LEGO bootloader service. Try removing the "LEGO Bootloader" device in your OS Bluetooth settings, then try again.',
),
);
// Possibly/probably caused by Chrome BlueZ back-end bug
// https://chromium-review.googlesource.com/c/chromium/src/+/2214098
dispatch(didFailToConnect(Reason.GattServiceNotFound));
return;
}
device.gatt.disconnect();
throw err;
}
dispatch(didConnect(char.writeValueWithoutResponse !== undefined));
// char.writeValueWithoutResponse() was introduced in Chrome 85.
// Older versions of Chrome for Android will write without response
// by default when using the deprecated writeValue().
const canWriteWithoutResponse =
char.writeValueWithoutResponse !== undefined ||
/Android/i.test(navigator.userAgent);
dispatch(didConnect(canWriteWithoutResponse));
} catch (err) {
dispatch(didError(err));
dispatch(didFailToConnect(Reason.Unknown, err));
}
}
+2 -10
View File
@@ -9,11 +9,7 @@ import { combineServices } from '.';
const decoder = new TextDecoder();
async function open(
action: Action,
_dispatch: Dispatch,
state: RootState,
): Promise<void> {
function open(action: Action, _dispatch: Dispatch, state: RootState): void {
if (action.type !== EditorActionType.Open) {
return;
}
@@ -26,11 +22,7 @@ async function open(
state.editor.current.getDocument().setValue(text);
}
async function save(
action: Action,
_dispatch: Dispatch,
state: RootState,
): Promise<void> {
function save(action: Action, _dispatch: Dispatch, state: RootState): void {
if (action.type !== EditorActionType.Save) {
return;
}
+16 -2
View File
@@ -2,11 +2,25 @@
// Copyright (c) 2020 The Pybricks Authors
import { Action } from '../actions';
import { BootloaderConnectionActionType } from '../actions/bootloader';
import {
BootloaderConnectionActionType,
BootloaderConnectionFailureReason,
} from '../actions/bootloader';
import { combineServices } from '.';
async function consoleLog(action: Action): Promise<void> {
/**
* Logs unexpected errors to console.error and expected errors to console.debug.
* @param action An action
*/
function consoleLog(action: Action): void {
switch (action.type) {
case BootloaderConnectionActionType.DidFailToConnect:
if (action.reason === BootloaderConnectionFailureReason.Unknown) {
console.error(action.err);
} else {
console.debug(action.err);
}
break;
case BootloaderConnectionActionType.DidError:
console.error(action.err);
break;
+15 -6
View File
@@ -8,7 +8,11 @@ import bootloader from './bootloader';
import editor from './editor';
import errorLog from './error-log';
type Service = (action: Action, dispatch: Dispatch, state: RootState) => Promise<void>;
type Service = (
action: Action,
dispatch: Dispatch,
state: RootState,
) => void | Promise<void>;
function runService(
service: Service,
@@ -16,15 +20,20 @@ function runService(
dispatch: Dispatch,
state: RootState,
): void {
service(action, dispatch, state).catch((err) =>
console.log(`Unhandled exception in service: ${err}`),
);
// Services are deferred so that the current action completes before
// dispatching another action by calling dispatch() in the service.
setTimeout(async () => {
try {
await service(action, dispatch, state);
} catch (err) {
console.log(`Unhandled exception in service: ${err}`);
}
}, 0);
}
export function combineServices(...services: Service[]): Service {
return (a, d, s): Promise<void> => {
return (a, d, s): void => {
services.forEach((x) => runService(x, a, d, s));
return Promise.resolve();
};
}
+294 -2
View File
@@ -62,6 +62,16 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.10.0":
version "7.10.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.0.tgz#a238837896edf35ee5fbfb074548d3256b4bc55d"
integrity sha512-ThoWCJHlgukbtCP79nAK4oLqZt5fVo70AHUni/y8Jotyg5rtJiG2FVl+iJjRNKIyl4hppqztLyAoEWcCvqyOFQ==
dependencies:
"@babel/types" "^7.10.0"
jsesc "^2.5.1"
lodash "^4.17.13"
source-map "^0.5.0"
"@babel/generator@^7.4.0", "@babel/generator@^7.9.0", "@babel/generator@^7.9.6":
version "7.9.6"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43"
@@ -296,6 +306,11 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7"
integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==
"@babel/parser@^7.10.0":
version "7.10.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.0.tgz#8eca3e71a73dd562c5222376b08253436bb4995b"
integrity sha512-fnDUl1Uy2gThM4IFVW4ISNHqr3cJrCsRkSCasFgx0XDO9JcttDS5ytyBc4Cu4X1+fjoo3IVvFbRD6TeFlHJlEQ==
"@babel/plugin-proposal-async-generator-functions@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f"
@@ -995,6 +1010,15 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.0.0":
version "7.10.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.0.tgz#f15d852ce16cd5fb3e219097a75f662710b249b1"
integrity sha512-aMLEQn5tcG49LEWrsEwxiRTdaJmvLem3+JMCMSeCy2TILau0IDVyWdm/18ACx7XOCady64FLt6KkHy28tkDQHQ==
dependencies:
"@babel/code-frame" "^7.8.3"
"@babel/parser" "^7.10.0"
"@babel/types" "^7.10.0"
"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
version "7.8.6"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
@@ -1004,6 +1028,21 @@
"@babel/parser" "^7.8.6"
"@babel/types" "^7.8.6"
"@babel/traverse@^7.0.0":
version "7.10.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.0.tgz#290935529881baf619398d94fd453838bef36740"
integrity sha512-NZsFleMaLF1zX3NxbtXI/JCs2RPOdpGru6UBdGsfhdsDsP+kFF+h2QQJnMJglxk0kc69YmMFs4A44OJY0tKo5g==
dependencies:
"@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.10.0"
"@babel/helper-function-name" "^7.9.5"
"@babel/helper-split-export-declaration" "^7.8.3"
"@babel/parser" "^7.10.0"
"@babel/types" "^7.10.0"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.13"
"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.9.0", "@babel/traverse@^7.9.6":
version "7.9.6"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442"
@@ -1028,6 +1067,15 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@babel/types@^7.10.0":
version "7.10.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.0.tgz#d47d92249e42393a5723aad5319035ae411e3e38"
integrity sha512-t41W8yWFyQFPOAAvPvjyRhejcLGnJTA3iRpFcDbEKwVJ3UnHQePFzLk8GagTsucJlImyNwrGikGsYURrWbQG8w==
dependencies:
"@babel/helper-validator-identifier" "^7.9.5"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@cnakazawa/watch@^1.0.3":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
@@ -1321,6 +1369,77 @@
lodash "^4.17.15"
lodash-es "^4.17.15"
"@shopify/dates@^0.3.6":
version "0.3.6"
resolved "https://registry.yarnpkg.com/@shopify/dates/-/dates-0.3.6.tgz#5118ae0b16cbe384dcb7ae19c21f17c6396e8302"
integrity sha512-dr71oU2x7ThQ7r7jzWWkk61+0nwHFSiIpZXIvlUDCJ/31rWZGWv9S1XDV7/rLJQgNfVIwA2x9eOz0CbYCAuL6Q==
dependencies:
"@shopify/decorators" "^1.1.11"
tslib "^1.9.3"
"@shopify/decorators@^1.1.11":
version "1.1.11"
resolved "https://registry.yarnpkg.com/@shopify/decorators/-/decorators-1.1.11.tgz#ae111160185d9f33aebbab4df401b4bea858f302"
integrity sha512-qE5y08Oh6ukSQuF7CIPaCs9oLy99nRv1Rmq9rhb7Q02DB9+8z6uNGVmhcftbrIs/7VEMlqk0LrfL6e0ijrxy3g==
dependencies:
"@shopify/function-enhancers" "^1.0.9"
"@shopify/function-enhancers@^1.0.9":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@shopify/function-enhancers/-/function-enhancers-1.0.9.tgz#aa95e49ca2a3be1c76259ebce078b607faf26007"
integrity sha512-iGoGIuJIFgWyEnEttjvtSH+5nQS6Lv4LAAooSNaviL10Ah+gLBfFcuSIj19fVLaRl9WxYSIu4sWqwnwn/W+n1g==
"@shopify/i18n@^0.1.10":
version "0.1.10"
resolved "https://registry.yarnpkg.com/@shopify/i18n/-/i18n-0.1.10.tgz#8f07f538cba43581ea79dc1104d351b30da6d03d"
integrity sha512-RCSMyiDIMrjdiG8BDCtlu2L+0CCM7XDiWx5VbAvSb0GteBRcH8BZHh+22LJt3rcbCNnbiyKlLg/7ikbSyEgzHg==
dependencies:
tslib "^1.9.3"
"@shopify/react-effect@^3.2.12":
version "3.2.12"
resolved "https://registry.yarnpkg.com/@shopify/react-effect/-/react-effect-3.2.12.tgz#81b641cee3f5f451cabc5dd11318f57756786e76"
integrity sha512-q4R2x+K3D/M1F5e32qTFLVrN+9BonQACQxu+GnKjQGdZaRqndKgaLUKQQZJbIhCa1/rcj8H/d1JEADeU1XvSrQ==
dependencies:
tslib "^1.9.3"
"@shopify/react-hooks@^1.10.0":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@shopify/react-hooks/-/react-hooks-1.10.0.tgz#39671f889872a345f7e60a635a3d9fcb2a487825"
integrity sha512-kgw/lUOhvd5hqOWVGT3Z41Yl9k9knr0s8n+m8YdQTIklww7QzDNV341XKslaRy0qHAf2GUw7JH5g8BQFm1ZQSA==
"@shopify/react-i18n@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@shopify/react-i18n/-/react-i18n-3.0.2.tgz#dd4a07185952707bae71b01bbec6ef3ce2087279"
integrity sha512-xfOXZgE/DDQQRFxAYGBelQjygcddRPHzUo/ejHP5aU1W2Bs7RqiIQFv/CpLghwO8rKZvKoaHPickEk7ULwbQ3w==
dependencies:
"@shopify/dates" "^0.3.6"
"@shopify/decorators" "^1.1.11"
"@shopify/function-enhancers" "^1.0.9"
"@shopify/i18n" "^0.1.10"
"@shopify/react-effect" "^3.2.12"
"@shopify/react-hooks" "^1.10.0"
"@shopify/useful-types" "^2.1.5"
"@types/hoist-non-react-statics" "^3.0.1"
change-case "^3.1.0"
glob "^7.1.4"
hoist-non-react-statics "^3.0.1"
lodash.clonedeep "^4.0.0"
lodash.merge "^4.0.0"
string-hash "^1.1.3"
tslib "^1.9.3"
optionalDependencies:
"@babel/template" "^7.0.0"
"@babel/traverse" "^7.0.0"
fs-extra "^8.1.0"
"@shopify/useful-types@^2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@shopify/useful-types/-/useful-types-2.1.5.tgz#9fd09dcdfe272d8eb2cdd8e94058456eefdf57fa"
integrity sha512-V+6gW+fzr+XY//4RyI6XVvwu9cvLVWt9rae1t8Lx2rPjGt/kIM6TdCzk/Lfhd5E3RUR7vVgvWTfTw1FtrxmYUw==
dependencies:
tslib "^1.9.3"
"@svgr/babel-plugin-add-jsx-attribute@^4.2.0":
version "4.2.0"
resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1"
@@ -1527,7 +1646,7 @@
"@types/minimatch" "*"
"@types/node" "*"
"@types/hoist-non-react-statics@^3.3.0":
"@types/hoist-non-react-statics@^3.0.1", "@types/hoist-non-react-statics@^3.3.0":
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==
@@ -2841,6 +2960,14 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
camel-case@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
dependencies:
no-case "^2.2.0"
upper-case "^1.1.1"
camel-case@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547"
@@ -2932,6 +3059,30 @@ chalk@^3.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
change-case@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.1.0.tgz#0e611b7edc9952df2e8513b27b42de72647dd17e"
integrity sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==
dependencies:
camel-case "^3.0.0"
constant-case "^2.0.0"
dot-case "^2.1.0"
header-case "^1.0.0"
is-lower-case "^1.1.0"
is-upper-case "^1.1.0"
lower-case "^1.1.1"
lower-case-first "^1.0.0"
no-case "^2.3.2"
param-case "^2.1.0"
pascal-case "^2.0.0"
path-case "^2.1.0"
sentence-case "^2.1.0"
snake-case "^2.1.0"
swap-case "^1.1.0"
title-case "^2.1.0"
upper-case "^1.1.1"
upper-case-first "^1.1.0"
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
@@ -3234,6 +3385,14 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0:
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
constant-case@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46"
integrity sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=
dependencies:
snake-case "^2.1.0"
upper-case "^1.1.1"
constants-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
@@ -3983,6 +4142,13 @@ domutils@^1.5.1, domutils@^1.7.0:
dom-serializer "0"
domelementtype "1"
dot-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-2.1.1.tgz#34dcf37f50a8e93c2b3bca8bb7fb9155c7da3bee"
integrity sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=
dependencies:
no-case "^2.2.0"
dot-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa"
@@ -5310,6 +5476,14 @@ he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
header-case@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d"
integrity sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=
dependencies:
no-case "^2.2.0"
upper-case "^1.1.3"
hex-color-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
@@ -5324,7 +5498,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.3.0:
hoist-non-react-statics@^3.0.1, hoist-non-react-statics@^3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@@ -5908,6 +6082,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
is-lower-case@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393"
integrity sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=
dependencies:
lower-case "^1.1.0"
is-number@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -6012,6 +6193,13 @@ is-typedarray@~1.0.0:
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
is-upper-case@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f"
integrity sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=
dependencies:
upper-case "^1.1.0"
is-utf8@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
@@ -6907,6 +7095,11 @@ lodash._reinterpolate@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
lodash.clonedeep@^4.0.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
@@ -6922,6 +7115,11 @@ lodash.memoize@^4.1.2:
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
lodash.merge@^4.0.0:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lodash.sortby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
@@ -6972,6 +7170,18 @@ loud-rejection@^1.0.0:
currently-unhandled "^0.4.1"
signal-exit "^3.0.0"
lower-case-first@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1"
integrity sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=
dependencies:
lower-case "^1.1.2"
lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
lower-case@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7"
@@ -7394,6 +7604,13 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
no-case@^2.2.0, no-case@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
dependencies:
lower-case "^1.1.1"
no-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8"
@@ -7910,6 +8127,13 @@ parallel-transform@^1.1.0:
inherits "^2.0.3"
readable-stream "^2.1.5"
param-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc=
dependencies:
no-case "^2.2.0"
param-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238"
@@ -7977,6 +8201,14 @@ parseurl@~1.3.2, parseurl@~1.3.3:
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
pascal-case@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e"
integrity sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=
dependencies:
camel-case "^3.0.0"
upper-case-first "^1.1.0"
pascal-case@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f"
@@ -7995,6 +8227,13 @@ path-browserify@0.0.1:
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
path-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5"
integrity sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=
dependencies:
no-case "^2.2.0"
path-dirname@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
@@ -9990,6 +10229,14 @@ send@0.17.1:
range-parser "~1.2.1"
statuses "~1.5.0"
sentence-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.1.tgz#1f6e2dda39c168bf92d13f86d4a918933f667ed4"
integrity sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=
dependencies:
no-case "^2.2.0"
upper-case-first "^1.1.2"
serialize-javascript@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
@@ -10161,6 +10408,13 @@ slice-ansi@^2.1.0:
astral-regex "^1.0.0"
is-fullwidth-code-point "^2.0.0"
snake-case@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f"
integrity sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=
dependencies:
no-case "^2.2.0"
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@@ -10427,6 +10681,11 @@ strict-uri-encode@^1.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
string-hash@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=
string-length@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
@@ -10686,6 +10945,14 @@ svgo@^1.0.0, svgo@^1.2.2:
unquote "~1.1.1"
util.promisify "~1.0.0"
swap-case@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3"
integrity sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=
dependencies:
lower-case "^1.1.1"
upper-case "^1.1.1"
symbol-observable@^1.0.3, symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
@@ -10809,6 +11076,14 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
title-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa"
integrity sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=
dependencies:
no-case "^2.2.0"
upper-case "^1.0.3"
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -10910,6 +11185,11 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
tslib@^1.9.3:
version "1.13.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
tsutils@^3.17.1:
version "3.17.1"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
@@ -11093,6 +11373,18 @@ upath@^1.1.1:
resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
upper-case-first@^1.1.0, upper-case-first@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115"
integrity sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=
dependencies:
upper-case "^1.1.1"
upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"