-
Retry
+ state={methodState}
+ >
+
{icon}
+
+
+ Retry
+
- )
-}
+ );
+};
-export default PushNotificationMethod
+export default PushNotificationMethod;
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
icon: {
width: "64px",
height: "64px",
display: "inline-block",
- }
-}))
\ No newline at end of file
+ },
+}));
diff --git a/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx b/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx
index 7218f1762..212a3dcc8 100644
--- a/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx
+++ b/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx
@@ -1,26 +1,28 @@
import React, { useState, useEffect } from "react";
+
import { Grid, makeStyles, Button } from "@material-ui/core";
-import MethodSelectionDialog from "./MethodSelectionDialog";
-import { SecondFactorMethod } from "../../../models/Methods";
import { useHistory, Switch, Route, Redirect } from "react-router";
-import LoginLayout from "../../../layouts/LoginLayout";
+import u2fApi from "u2f-api";
+
import { useNotifications } from "../../../hooks/NotificationsContext";
+import LoginLayout from "../../../layouts/LoginLayout";
+import { Configuration } from "../../../models/Configuration";
+import { SecondFactorMethod } from "../../../models/Methods";
+import { UserInfo } from "../../../models/UserInfo";
import {
- initiateTOTPRegistrationProcess,
- initiateU2FRegistrationProcess
-} from "../../../services/RegisterDevice";
-import SecurityKeyMethod from "./SecurityKeyMethod";
+ LogoutRoute as SignOutRoute,
+ SecondFactorTOTPRoute,
+ SecondFactorPushRoute,
+ SecondFactorU2FRoute,
+ SecondFactorRoute,
+} from "../../../Routes";
+import { initiateTOTPRegistrationProcess, initiateU2FRegistrationProcess } from "../../../services/RegisterDevice";
+import { AuthenticationLevel } from "../../../services/State";
+import { setPreferred2FAMethod } from "../../../services/UserPreferences";
+import MethodSelectionDialog from "./MethodSelectionDialog";
import OneTimePasswordMethod from "./OneTimePasswordMethod";
import PushNotificationMethod from "./PushNotificationMethod";
-import {
- LogoutRoute as SignOutRoute, SecondFactorTOTPRoute,
- SecondFactorPushRoute, SecondFactorU2FRoute, SecondFactorRoute
-} from "../../../Routes";
-import { setPreferred2FAMethod } from "../../../services/UserPreferences";
-import { UserInfo } from "../../../models/UserInfo";
-import { Configuration } from "../../../models/Configuration";
-import u2fApi from "u2f-api";
-import { AuthenticationLevel } from "../../../services/State";
+import SecurityKeyMethod from "./SecurityKeyMethod";
const EMAIL_SENT_NOTIFICATION = "An email has been sent to your address to complete the process.";
@@ -46,7 +48,8 @@ const SecondFactorForm = function (props: Props) {
useEffect(() => {
u2fApi.ensureSupport().then(
() => setU2fSupported(true),
- () => console.error("U2F not supported"));
+ () => console.error("U2F not supported"),
+ );
}, [setU2fSupported]);
const initiateRegistration = (initiateRegistrationFunc: () => Promise
) => {
@@ -63,12 +66,12 @@ const SecondFactorForm = function (props: Props) {
createErrorNotification("There was a problem initiating the registration process");
}
setRegistrationInProgress(false);
- }
- }
+ };
+ };
const handleMethodSelectionClick = () => {
setMethodSelectionOpen(true);
- }
+ };
const handleMethodSelected = async (method: SecondFactorMethod) => {
try {
@@ -79,23 +82,21 @@ const SecondFactorForm = function (props: Props) {
console.error(err);
createErrorNotification("There was an issue updating preferred second factor method");
}
- }
+ };
const handleLogoutClick = () => {
history.push(SignOutRoute);
- }
+ };
return (
-
+
setMethodSelectionOpen(false)}
- onClick={handleMethodSelected} />
+ onClick={handleMethodSelected}
+ />
@@ -116,8 +117,9 @@ const SecondFactorForm = function (props: Props) {
registered={props.userInfo.has_totp}
totp_period={props.configuration.totp_period}
onRegisterClick={initiateRegistration(initiateTOTPRegistrationProcess)}
- onSignInError={err => createErrorNotification(err.message)}
- onSignInSuccess={props.onAuthenticationSuccess} />
+ onSignInError={(err) => createErrorNotification(err.message)}
+ onSignInSuccess={props.onAuthenticationSuccess}
+ />
createErrorNotification(err.message)}
- onSignInSuccess={props.onAuthenticationSuccess} />
+ onSignInError={(err) => createErrorNotification(err.message)}
+ onSignInSuccess={props.onAuthenticationSuccess}
+ />
createErrorNotification(err.message)}
- onSignInSuccess={props.onAuthenticationSuccess} />
+ onSignInError={(err) => createErrorNotification(err.message)}
+ onSignInSuccess={props.onAuthenticationSuccess}
+ />
@@ -143,12 +147,12 @@ const SecondFactorForm = function (props: Props) {
- )
-}
+ );
+};
-export default SecondFactorForm
+export default SecondFactorForm;
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
methodContainer: {
border: "1px solid #d6d6d6",
borderRadius: "10px",
@@ -156,4 +160,4 @@ const useStyles = makeStyles(theme => ({
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
},
-}))
+}));
diff --git a/web/src/views/LoginPortal/SecondFactor/SecurityKeyMethod.tsx b/web/src/views/LoginPortal/SecondFactor/SecurityKeyMethod.tsx
index 97a4e22b0..b8c825e94 100644
--- a/web/src/views/LoginPortal/SecondFactor/SecurityKeyMethod.tsx
+++ b/web/src/views/LoginPortal/SecondFactor/SecurityKeyMethod.tsx
@@ -1,17 +1,19 @@
import React, { useCallback, useEffect, useState, Fragment } from "react";
-import MethodContainer, { State as MethodContainerState } from "./MethodContainer";
+
import { makeStyles, Button, useTheme } from "@material-ui/core";
-import { initiateU2FSignin, completeU2FSignin } from "../../../services/SecurityKey";
-import u2fApi from "u2f-api";
-import { useRedirectionURL } from "../../../hooks/RedirectionURL";
-import { useIsMountedRef } from "../../../hooks/Mounted";
-import { useTimer } from "../../../hooks/Timer";
-import LinearProgressBar from "../../../components/LinearProgressBar";
-import FingerTouchIcon from "../../../components/FingerTouchIcon";
-import FailureIcon from "../../../components/FailureIcon";
-import IconWithContext from "./IconWithContext";
import { CSSProperties } from "@material-ui/styles";
+import u2fApi from "u2f-api";
+
+import FailureIcon from "../../../components/FailureIcon";
+import FingerTouchIcon from "../../../components/FingerTouchIcon";
+import LinearProgressBar from "../../../components/LinearProgressBar";
+import { useIsMountedRef } from "../../../hooks/Mounted";
+import { useRedirectionURL } from "../../../hooks/RedirectionURL";
+import { useTimer } from "../../../hooks/Timer";
+import { initiateU2FSignin, completeU2FSignin } from "../../../services/SecurityKey";
import { AuthenticationLevel } from "../../../services/State";
+import IconWithContext from "./IconWithContext";
+import MethodContainer, { State as MethodContainerState } from "./MethodContainer";
export enum State {
WaitTouch = 1,
@@ -35,7 +37,7 @@ const SecurityKeyMethod = function (props: Props) {
const style = useStyles();
const redirectionURL = useRedirectionURL();
const mounted = useIsMountedRef();
- const [timerPercent, triggerTimer,] = useTimer(signInTimeout * 1000 - 500);
+ const [timerPercent, triggerTimer] = useTimer(signInTimeout * 1000 - 500);
const { onSignInSuccess, onSignInError } = props;
/* eslint-disable react-hooks/exhaustive-deps */
@@ -61,7 +63,7 @@ const SecurityKeyMethod = function (props: Props) {
challenge: signRequest.challenge,
keyHandle: r.keyHandle,
version: r.version,
- })
+ });
}
const signResponse = await u2fApi.sign(signRequests, signInTimeout);
// If the request was initiated and the user changed 2FA method in the meantime,
@@ -79,9 +81,19 @@ const SecurityKeyMethod = function (props: Props) {
onSignInErrorCallback(new Error("Failed to initiate security key sign in process"));
setState(State.Failure);
}
- }, [onSignInSuccessCallback, onSignInErrorCallback, redirectionURL, mounted, triggerTimer, props.authenticationLevel, props.registered]);
+ }, [
+ onSignInSuccessCallback,
+ onSignInErrorCallback,
+ redirectionURL,
+ mounted,
+ triggerTimer,
+ props.authenticationLevel,
+ props.registered,
+ ]);
- useEffect(() => { doInitiateSignIn() }, [doInitiateSignIn]);
+ useEffect(() => {
+ doInitiateSignIn();
+ }, [doInitiateSignIn]);
let methodState = MethodContainerState.METHOD;
if (props.authenticationLevel === AuthenticationLevel.TwoFactor) {
@@ -96,20 +108,21 @@ const SecurityKeyMethod = function (props: Props) {
title="Security Key"
explanation="Touch the token of your security key"
state={methodState}
- onRegisterClick={props.onRegisterClick}>
+ onRegisterClick={props.onRegisterClick}
+ >
- )
-}
+ );
+};
-export default SecurityKeyMethod
+export default SecurityKeyMethod;
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
icon: {
display: "inline-block",
- }
+ },
}));
interface IconProps {
@@ -125,22 +138,32 @@ function Icon(props: IconProps) {
const progressBarStyle: CSSProperties = {
marginTop: theme.spacing(),
- }
+ };
- const touch = }
- context={ }
- className={state === State.WaitTouch ? undefined : "hidden"} />
+ const touch = (
+ }
+ context={ }
+ className={state === State.WaitTouch ? undefined : "hidden"}
+ />
+ );
- const failure = }
- context={Retry }
- className={state === State.Failure ? undefined : "hidden"} />
+ const failure = (
+ }
+ context={
+
+ Retry
+
+ }
+ className={state === State.Failure ? undefined : "hidden"}
+ />
+ );
return (
{touch}
{failure}
- )
+ );
}
diff --git a/web/src/views/LoginPortal/SignOut/SignOut.tsx b/web/src/views/LoginPortal/SignOut/SignOut.tsx
index 056ac5de5..b44a4b73a 100644
--- a/web/src/views/LoginPortal/SignOut/SignOut.tsx
+++ b/web/src/views/LoginPortal/SignOut/SignOut.tsx
@@ -1,14 +1,16 @@
import React, { useEffect, useCallback, useState } from "react";
-import LoginLayout from "../../../layouts/LoginLayout";
-import { useNotifications } from "../../../hooks/NotificationsContext";
-import { signOut } from "../../../services/SignOut";
+
import { Typography, makeStyles } from "@material-ui/core";
import { Redirect } from "react-router";
-import { FirstFactorRoute } from "../../../Routes";
-import { useRedirectionURL } from "../../../hooks/RedirectionURL";
-import { useIsMountedRef } from "../../../hooks/Mounted";
-export interface Props { }
+import { useIsMountedRef } from "../../../hooks/Mounted";
+import { useNotifications } from "../../../hooks/NotificationsContext";
+import { useRedirectionURL } from "../../../hooks/RedirectionURL";
+import LoginLayout from "../../../layouts/LoginLayout";
+import { FirstFactorRoute } from "../../../Routes";
+import { signOut } from "../../../services/SignOut";
+
+export interface Props {}
const SignOut = function (props: Props) {
const mounted = useIsMountedRef();
@@ -33,29 +35,29 @@ const SignOut = function (props: Props) {
}
}, [createErrorNotification, setTimedOut, mounted]);
- useEffect(() => { doSignOut() }, [doSignOut]);
+ useEffect(() => {
+ doSignOut();
+ }, [doSignOut]);
if (timedOut) {
if (redirectionURL) {
window.location.href = redirectionURL;
} else {
- return
+ return ;
}
}
return (
-
- You're being signed out and redirected...
-
+ You're being signed out and redirected...
- )
-}
+ );
+};
-export default SignOut
+export default SignOut;
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
typo: {
padding: theme.spacing(),
- }
-}))
\ No newline at end of file
+ },
+}));
diff --git a/web/src/views/ResetPassword/ResetPasswordStep1.tsx b/web/src/views/ResetPassword/ResetPasswordStep1.tsx
index 2709cb8c7..97e52f39e 100644
--- a/web/src/views/ResetPassword/ResetPasswordStep1.tsx
+++ b/web/src/views/ResetPassword/ResetPasswordStep1.tsx
@@ -1,11 +1,13 @@
import React, { useState } from "react";
-import LoginLayout from "../../layouts/LoginLayout";
+
import { Grid, Button, makeStyles } from "@material-ui/core";
-import { useNotifications } from "../../hooks/NotificationsContext";
import { useHistory } from "react-router";
-import { initiateResetPasswordProcess } from "../../services/ResetPassword";
-import { FirstFactorRoute } from "../../Routes";
+
import FixedTextField from "../../components/FixedTextField";
+import { useNotifications } from "../../hooks/NotificationsContext";
+import LoginLayout from "../../layouts/LoginLayout";
+import { FirstFactorRoute } from "../../Routes";
+import { initiateResetPasswordProcess } from "../../services/ResetPassword";
const ResetPasswordStep1 = function () {
const style = useStyles();
@@ -26,15 +28,15 @@ const ResetPasswordStep1 = function () {
} catch (err) {
createErrorNotification("There was an issue initiating the password reset process.");
}
- }
+ };
const handleResetClick = () => {
doInitiateResetPasswordProcess();
- }
+ };
const handleCancelClick = () => {
history.push(FirstFactorRoute);
- }
+ };
return (
@@ -49,19 +51,17 @@ const ResetPasswordStep1 = function () {
value={username}
onChange={(e) => setUsername(e.target.value)}
onKeyPress={(ev) => {
- if (ev.key === 'Enter') {
+ if (ev.key === "Enter") {
doInitiateResetPasswordProcess();
ev.preventDefault();
}
- }} />
+ }}
+ />
- Reset
+
+ Reset
+
Cancel
+ onClick={handleCancelClick}
+ >
+ Cancel
+
- )
-}
+ );
+};
-export default ResetPasswordStep1
+export default ResetPasswordStep1;
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
root: {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
},
-}))
\ No newline at end of file
+}));
diff --git a/web/src/views/ResetPassword/ResetPasswordStep2.tsx b/web/src/views/ResetPassword/ResetPasswordStep2.tsx
index 43c4b8a7f..af3dc5b7a 100644
--- a/web/src/views/ResetPassword/ResetPasswordStep2.tsx
+++ b/web/src/views/ResetPassword/ResetPasswordStep2.tsx
@@ -1,13 +1,15 @@
import React, { useState, useCallback, useEffect } from "react";
-import LoginLayout from "../../layouts/LoginLayout";
-import classnames from "classnames";
+
import { Grid, Button, makeStyles } from "@material-ui/core";
-import { useNotifications } from "../../hooks/NotificationsContext";
+import classnames from "classnames";
import { useHistory, useLocation } from "react-router";
-import { completeResetPasswordProcess, resetPassword } from "../../services/ResetPassword";
-import { FirstFactorRoute } from "../../Routes";
-import { extractIdentityToken } from "../../utils/IdentityToken";
+
import FixedTextField from "../../components/FixedTextField";
+import { useNotifications } from "../../hooks/NotificationsContext";
+import LoginLayout from "../../layouts/LoginLayout";
+import { FirstFactorRoute } from "../../Routes";
+import { completeResetPasswordProcess, resetPassword } from "../../services/ResetPassword";
+import { extractIdentityToken } from "../../utils/IdentityToken";
const ResetPasswordStep2 = function () {
const style = useStyles();
@@ -36,8 +38,9 @@ const ResetPasswordStep2 = function () {
setFormDisabled(false);
} catch (err) {
console.error(err);
- createErrorNotification("There was an issue completing the process. " +
- "The verification token might have expired.");
+ createErrorNotification(
+ "There was an issue completing the process. The verification token might have expired.",
+ );
setFormDisabled(true);
}
}, [processToken, createErrorNotification]);
@@ -54,11 +57,11 @@ const ResetPasswordStep2 = function () {
if (password2 === "") {
setErrorPassword2(true);
}
- return
+ return;
}
if (password1 !== password2) {
setErrorPassword1(true);
- setErrorPassword2(true)
+ setErrorPassword2(true);
createErrorNotification("Passwords do not match.");
return;
}
@@ -76,13 +79,11 @@ const ResetPasswordStep2 = function () {
createErrorNotification("There was an issue resetting the password.");
}
}
- }
+ };
- const handleResetClick = () =>
- doResetPassword();
+ const handleResetClick = () => doResetPassword();
- const handleCancelClick = () =>
- history.push(FirstFactorRoute);
+ const handleCancelClick = () => history.push(FirstFactorRoute);
return (
@@ -95,9 +96,10 @@ const ResetPasswordStep2 = function () {
type="password"
value={password1}
disabled={formDisabled}
- onChange={e => setPassword1(e.target.value)}
+ onChange={(e) => setPassword1(e.target.value)}
error={errorPassword1}
- className={classnames(style.fullWidth)} />
+ className={classnames(style.fullWidth)}
+ />
setPassword2(e.target.value)}
+ onChange={(e) => setPassword2(e.target.value)}
error={errorPassword2}
onKeyPress={(ev) => {
- if (ev.key === 'Enter') {
+ if (ev.key === "Enter") {
doResetPassword();
ev.preventDefault();
}
}}
- className={classnames(style.fullWidth)} />
+ className={classnames(style.fullWidth)}
+ />
Reset
+ className={style.fullWidth}
+ >
+ Reset
+
Cancel
+ className={style.fullWidth}
+ >
+ Cancel
+
- )
-}
+ );
+};
-export default ResetPasswordStep2
+export default ResetPasswordStep2;
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
root: {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
},
fullWidth: {
width: "100%",
- }
-}))
\ No newline at end of file
+ },
+}));
diff --git a/web/types/index.d.ts b/web/types/index.d.ts
index 85e730f8e..74d1869b4 100644
--- a/web/types/index.d.ts
+++ b/web/types/index.d.ts
@@ -1 +1 @@
-///
\ No newline at end of file
+///
diff --git a/web/types/react-otp-input/index.d.ts b/web/types/react-otp-input/index.d.ts
index a872f08d0..f7bb33ed0 100644
--- a/web/types/react-otp-input/index.d.ts
+++ b/web/types/react-otp-input/index.d.ts
@@ -1,2 +1 @@
-
-declare module 'react-otp-input';
\ No newline at end of file
+declare module "react-otp-input";
diff --git a/web/yarn.lock b/web/yarn.lock
index 48acf0b1e..110b41e9b 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -4780,6 +4780,11 @@ escodegen@^1.14.1:
optionalDependencies:
source-map "~0.6.1"
+eslint-config-prettier@^7.1.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz#5402eb559aa94b894effd6bddfa0b1ca051c858f"
+ integrity sha512-9sm5/PxaFG7qNJvJzTROMM1Bk1ozXVTKI0buKOyb0Bsr1hrwi0H/TzxF/COtf1uxikIK8SwhX7K6zg78jAzbeA==
+
eslint-config-react-app@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz#ccff9fc8e36b322902844cbd79197982be355a0e"
@@ -4787,6 +4792,11 @@ eslint-config-react-app@^6.0.0:
dependencies:
confusing-browser-globals "^1.0.10"
+eslint-formatter-rdjson@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/eslint-formatter-rdjson/-/eslint-formatter-rdjson-1.0.3.tgz#ab1bb2174aefdc802befaaf7f385d44b97f6d9a4"
+ integrity sha512-YqqNcP+xiLEWXz1GdAGKhnIRgtjOeiTPoG/hSIx/SzOt4n+fwcxRuiJE3DKpfSIJjodXS617qfRa6cZx/kIkbw==
+
eslint-import-resolver-node@^0.3.4:
version "0.3.4"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717"
@@ -4795,6 +4805,17 @@ eslint-import-resolver-node@^0.3.4:
debug "^2.6.9"
resolve "^1.13.1"
+eslint-import-resolver-typescript@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.3.0.tgz#0870988098bc6c6419c87705e6b42bee89425445"
+ integrity sha512-MHSXvmj5e0SGOOBhBbt7C+fWj1bJbtSYFAD85Xeg8nvUtuooTod2HQb8bfhE9f5QyyNxEfgzqOYFCvmdDIcCuw==
+ dependencies:
+ debug "^4.1.1"
+ glob "^7.1.6"
+ is-glob "^4.0.1"
+ resolve "^1.17.0"
+ tsconfig-paths "^3.9.0"
+
eslint-module-utils@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6"
@@ -4854,6 +4875,13 @@ eslint-plugin-jsx-a11y@^6.3.1:
jsx-ast-utils "^3.1.0"
language-tags "^1.0.5"
+eslint-plugin-prettier@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz#61e295349a65688ffac0b7808ef0a8244bdd8d40"
+ integrity sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ==
+ dependencies:
+ prettier-linter-helpers "^1.0.0"
+
eslint-plugin-react-hooks@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556"
@@ -5240,6 +5268,11 @@ fast-deep-equal@^3.1.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
+fast-diff@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
+ integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
+
fast-glob@^3.1.1:
version "3.2.4"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3"
@@ -9353,6 +9386,18 @@ prepend-http@^1.0.0:
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
+prettier-linter-helpers@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
+ integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
+ dependencies:
+ fast-diff "^1.1.2"
+
+prettier@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
+ integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
+
pretty-bytes@^5.3.0:
version "5.4.1"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b"