From e1e2d7d715aaa3cb4760048656e3f2778bb6457e Mon Sep 17 00:00:00 2001 From: Maksim Karasev Date: Sat, 11 Jun 2022 00:36:20 +0300 Subject: [PATCH] Migrate to MUI v5 --- .vscode/settings.json | 11 +- package.json | 2 +- packages/server/package.json | 6 +- packages/web/package.json | 25 +- packages/web/src/App.test.tsx | 9 - packages/web/src/App.tsx | 220 +++---- .../web/src/components/ConfiguarionDialog.tsx | 86 +-- .../web/src/components/ConfirmationDialog.tsx | 8 +- .../src/components/CredentialChangeDialog.tsx | 47 +- packages/web/src/components/ImageGridList.tsx | 34 +- .../web/src/components/ImageThumbnail.tsx | 61 +- packages/web/src/components/LoginView.tsx | 62 +- .../web/src/components/PicturesAppBar.tsx | 98 +--- packages/web/src/components/UploadDialog.tsx | 94 +-- packages/web/src/i18n.ts | 3 +- packages/web/src/index.tsx | 21 +- packages/web/src/reportWebVitals.ts | 1 + packages/web/src/service-worker.ts | 9 +- packages/web/src/serviceWorkerRegistration.ts | 3 +- packages/web/src/services/common.ts | 4 + packages/web/src/services/images.ts | 37 +- packages/web/src/services/login.ts | 18 +- packages/web/src/services/meta.ts | 17 +- packages/web/src/services/settings.ts | 1 + packages/web/src/services/user.ts | 25 +- yarn.lock | 553 ++++++++++++++---- 26 files changed, 912 insertions(+), 543 deletions(-) delete mode 100644 packages/web/src/App.test.tsx create mode 100644 packages/web/src/services/common.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 134d876..1708095 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,7 @@ { - "prettier.enable": false, "editor.defaultFormatter": "dbaeumer.vscode-eslint", - "eslint.workingDirectories": [ - "./packages/web", - "./packages/server" - ] -} \ No newline at end of file + "eslint.workingDirectories": ["./packages/web", "./packages/server"], + "editor.codeActionsOnSave": { + "source.fixAll": true + } +} diff --git a/package.json b/package.json index b6e9241..eaf127a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "personal-gallery", - "version": "1.0.0", + "version": "1.1.0", "description": "", "scripts": { "server-dev": "yarn workspace server dev", diff --git a/packages/server/package.json b/packages/server/package.json index 369f0ae..634c0aa 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "server", - "version": "1.0.0", + "version": "1.1.0", "description": "", "main": "index.js", "scripts": { @@ -43,8 +43,8 @@ "jest": "^26.6.3", "supertest": "^6.0.1", "ts-jest": "^26.4.4", - "ts-node": "^9.1.1", - "ts-node-dev": "^1.1.1", + "ts-node": "^10.8.1", + "ts-node-dev": "^2.0.0", "typescript": "^4.1.3" }, "dependencies": { diff --git a/packages/web/package.json b/packages/web/package.json index 3d88173..6659475 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,10 +1,13 @@ { "name": "web", - "version": "0.1.0", + "version": "1.1.0", "private": true, "dependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", "@fontsource/roboto": "^4.2.1", - "@material-ui/core": "^4.11.3", + "@mui/material": "^5.8.2", + "@mui/styles": "^5.8.0", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", @@ -35,7 +38,7 @@ "test": "react-scripts test", "eject": "react-scripts eject" }, - "proxy": "http://localhost:3002", + "proxy": "http://localhost:3001", "eslintConfig": { "extends": [ "react-app", @@ -67,7 +70,19 @@ "location": "anywhere" } ], - "linebreak-style": 0 + "linebreak-style": 0, + "no-void": [ + "error", + { + "allowAsStatement": true + } + ], + "@typescript-eslint/no-misused-promises": [ + "error", + { + "checksVoidReturn": false + } + ] } }, "browserslist": { @@ -94,4 +109,4 @@ "eslint-plugin-react-hooks": "^4.0.8", "react-scripts": "^5.0.1" } -} \ No newline at end of file +} diff --git a/packages/web/src/App.test.tsx b/packages/web/src/App.test.tsx deleted file mode 100644 index 2a68616..0000000 --- a/packages/web/src/App.test.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/packages/web/src/App.tsx b/packages/web/src/App.tsx index f662a06..36a18db 100644 --- a/packages/web/src/App.tsx +++ b/packages/web/src/App.tsx @@ -1,21 +1,22 @@ +/** @jsxImportSource @emotion/react */ import React, { useEffect, useRef, useState } from 'react'; import { Container, - makeStyles, Theme, - createStyles, - withWidth, - WithWidth, Dialog, CircularProgress, IconButton, Snackbar, Grid, Typography, -} from '@material-ui/core'; + Breakpoint, + useMediaQuery, +} from '@mui/material'; +import { css } from '@emotion/react'; import InfiniteScroll from 'react-infinite-scroller'; -import { AxiosError } from 'axios'; +import axios from 'axios'; import { useTranslation } from 'react-i18next'; +import { useTheme } from '@mui/styles'; import * as imageService from './services/images'; import * as settingsService from './services/settings'; import * as loginService from './services/login'; @@ -32,62 +33,22 @@ import LoginView from './components/LoginView'; import ConfirmationDialog from './components/ConfirmationDialog'; import CredentialChangeDialog from './components/CredentialChangeDialog'; -const useStyles = makeStyles((theme: Theme) => createStyles({ - root: { - height: '100vh', - }, - titleBar: { - background: - 'linear-gradient(to bottom, rgba(0,0,0,0) 0%, ' - + 'rgba(0,0,0,0) 70%, rgba(0,0,0,0) 100%)', - transition: 'background 2s ease-out', - '&:hover': { - background: - 'linear-gradient(to bottom, rgba(0,0,0,0) 0%, ' - + 'rgba(0,0,0,0) 70%, rgba(0,0,0,0) 100%)', - }, - }, - icon: { - color: 'white', - filter: 'drop-shadow(2px 4px 3px #222222)', - }, - listItem: { - cursor: 'pointer', - '&:hover': { - opacity: '0.9', - }, - }, - dialogImage: { - maxHeight: '80vh', - }, - loader: { - margin: '1rem', - }, - toolbarTitle: { - flexGrow: 1, - }, - toolbarButton: { - flexGrow: 1, - }, - placeholderText: { - textAlign: 'center', - margin: theme.spacing(1), - color: '#696969', - }, - placeholderIconContainer: { - textAlign: 'center', - color: '#696969', - }, - placeholderIcon: { - fontSize: '96px', - verticalAlign: '-25%', - }, -})); +function useWidth() { + const theme: Theme = useTheme(); + const keys: readonly Breakpoint[] = [...theme.breakpoints.keys].reverse(); + return ( + keys.reduce((output: Breakpoint | null, key: Breakpoint) => { + // eslint-disable-next-line react-hooks/rules-of-hooks + const matches = useMediaQuery(theme.breakpoints.up(key)); + return !output && matches ? key : output; + }, null) || 'xs' + ); +} -function App(props: WithWidth) { +function App() { const [modalImage, setModalImage] = useState(''); const [modalVideo, setModalVideo] = useState(''); - const [imagesData, setImagesData] = useState(undefined); + const [imagesData, setImagesData] = useState<{ [key: number]: Image[]; }>({}); const imagesPage = useRef(0); const [hasMore, setHasMore] = useState(true); const [userSettings, setUserSettings] = useState( @@ -114,14 +75,65 @@ function App(props: WithWidth) { const [setupFinished, setSetupFinished] = useState(true); const [apiKey, setApiKey] = useState(); - const { width } = props; + const theme: Theme = useTheme(); + const styles = { + root: css({ + height: '100vh', + }), + titleBar: css({ + background: + 'linear-gradient(to bottom, rgba(0,0,0,0) 0%, ' + + 'rgba(0,0,0,0) 70%, rgba(0,0,0,0) 100%)', + transition: 'background 2s ease-out', + '&:hover': { + background: + 'linear-gradient(to bottom, rgba(0,0,0,0) 0%, ' + + 'rgba(0,0,0,0) 70%, rgba(0,0,0,0) 100%)', + }, + }), + icon: css({ + color: 'white', + filter: 'drop-shadow(2px 4px 3px #222222)', + }), + listItem: css({ + cursor: 'pointer', + '&:hover': { + opacity: '0.9', + }, + }), + dialogImage: css({ + maxHeight: '80vh', + }), + loader: css({ + margin: '1rem', + }), + toolbarTitle: css({ + flexGrow: 1, + }), + toolbarButton: css({ + flexGrow: 1, + }), + placeholderText: css({ + textAlign: 'center', + margin: theme.spacing(1), + color: '#696969', + }), + placeholderIconContainer: css({ + textAlign: 'center', + color: '#696969', + }), + placeholderIcon: css({ + fontSize: '96px', + verticalAlign: '-25%', + }), + }; + const width = useWidth(); const { t } = useTranslation(); const widthMap = { xs: 3, sm: 4, md: 5, lg: 6, xl: 6, }; const cols = widthMap[width]; - const classes = useStyles(); useEffect(() => { // imageService.getAll().then(result => setImagesData(result)); @@ -130,7 +142,7 @@ function App(props: WithWidth) { setSetupFinished(result.setupFinished); setUserSettings(settingsService.getSettings()); setUserLoggedIn(settingsService.getUserState()); - }); + }).catch((e) => console.error(e)); }, []); const imageTileClickHandler = (url: string) => { if (/\.(mp4|webm)$/.test(url)) { @@ -140,9 +152,9 @@ function App(props: WithWidth) { } }; - const handleLogout = async (clientOnly: boolean = false) => { + const handleLogout = async (clientOnly = false) => { if (!clientOnly) { - loginService.doLogout(); + await loginService.doLogout(); } setUserLoggedIn(false); setDragOpen(false); @@ -166,17 +178,19 @@ function App(props: WithWidth) { if (result.length === 0) { setHasMore(false); } else { - setImagesData((data: any) => ({ ...data, [page]: result })); + setImagesData((data) => ({ ...data, [page]: result })); } }) - .catch((e: AxiosError) => { - if (e.response?.status === 401) { - handleLogout(true); - setNotification(t('Authorization error, please login')); - } else { - setNotification(t('Error getting image list from server')); + .catch((e) => { + if (axios.isAxiosError(e)) { + if (e.response?.status === 401) { + void handleLogout(true); + setNotification(t('Authorization error, please login')); + } else { + setNotification(t('Error getting image list from server')); + } + imagesPage.current -= 1; } - imagesPage.current -= 1; }); imagesPage.current += 1; }; @@ -193,7 +207,7 @@ function App(props: WithWidth) { try { const combinedResult = await Promise.all(promises); if (combinedResult.length > 0) { - setImagesData((data: { [key:number]: Image[] }) => { + setImagesData((data) => { if (data === undefined || Object.keys(data).length === 0) { return { [-1]: combinedResult }; } @@ -215,7 +229,7 @@ function App(props: WithWidth) { if (acceptedUploadFiletypes.includes(item.type)) { const pasteAsFile = item.getAsFile(); if (pasteAsFile !== null) { - handleUpload([pasteAsFile]); + void handleUpload([pasteAsFile]); } } }); @@ -272,10 +286,10 @@ function App(props: WithWidth) { ) => { try { await userService.updateCredentials(oldPassword, username, password); - handleLogout(); + void handleLogout(); setNotification(t('Please login with your new credentials')); - } catch (e: any) { - if (e.response.status === 401) { + } catch (e) { + if (axios.isAxiosError(e) && e?.response?.status === 401) { setNotification(t('Check your old password and try again')); } } @@ -284,13 +298,13 @@ function App(props: WithWidth) { if (userSettings === undefined || userLoggedIn === undefined) { return ( - + ); } return (
setDragOpen(true)} onPaste={handlePaste} > @@ -308,28 +322,34 @@ function App(props: WithWidth) { hasMore={hasMore} loader={( - + )} > {typeof imagesData === 'object' && Object.keys(imagesData).length !== 0 ? ( a - b).reduce( - (r, k) => (r.concat(imagesData[k])), - [], - ))]} + images={ + [ + ...new Set(Object.keys(imagesData) + .map(Number) + .sort((a:number, b:number) => a - b) + .reduce( + (r: Image[], k) => (r.concat(imagesData[k])), + [], + ))] +} cols={cols} onTileClick={imageTileClickHandler} onNotification={setNotification} /> ) : ( -
- +
+ insert_photo
- + {t('Upload your first image')} @@ -352,12 +372,12 @@ function App(props: WithWidth) { maxWidth="lg" > {modalImage !== '' ? ( - + ) : null} {modalVideo !== '' ? ( // eslint-disable-next-line jsx-a11y/media-has-caption
); } -export default withWidth()(App); +export default App; diff --git a/packages/web/src/components/ConfiguarionDialog.tsx b/packages/web/src/components/ConfiguarionDialog.tsx index ce1b345..a8ba6c1 100644 --- a/packages/web/src/components/ConfiguarionDialog.tsx +++ b/packages/web/src/components/ConfiguarionDialog.tsx @@ -1,6 +1,6 @@ +/** @jsxImportSource @emotion/react */ import { Button, - createStyles, Dialog, DialogActions, DialogContent, @@ -9,43 +9,22 @@ import { FormControlLabel, FormLabel, InputLabel, - makeStyles, MenuItem, Radio, RadioGroup, Select, Theme, Tooltip, -} from '@material-ui/core'; +} from '@mui/material'; +import { css } from '@emotion/react'; import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useTheme } from '@mui/styles'; import generateConfig from '../utils/ShareX'; import { availableLanguages } from '../i18n'; import { Config, SortBy, SortOrder } from '../types'; -const useStyles = makeStyles((theme: Theme) => createStyles({ - form: { - display: 'flex', - flexDirection: 'column', - margin: 'auto', - width: 'fit-content', - }, - formControl: { - margin: theme.spacing(1), - }, - wide: { - width: '100%', - }, - buttonSpan: { - display: 'inline-flex', - flexGrow: 1, - }, - button: { - flexGrow: 1, - }, -})); - -const ConfigurationDialog = ({ +function ConfigurationDialog({ open, onDialogClose, currentSettings, @@ -61,11 +40,33 @@ const ConfigurationDialog = ({ onApiKeyChange: () => void; onCredentialsChange: () => void; apiKey?: string; -}) => { +}) { const [sortBy, setSortBy] = useState(currentSettings.sortBy); const [sortOrder, setSortOrder] = useState(currentSettings.sortOrder); - const classes = useStyles(); const { t, i18n } = useTranslation(); + const theme: Theme = useTheme(); + + const styles = { + form: css({ + display: 'flex', + flexDirection: 'column', + margin: 'auto', + width: 'fit-content', + }), + formControl: css({ + margin: theme.spacing(1), + }), + wide: css({ + width: '100%', + }), + buttonSpan: css({ + display: 'inline-flex', + flexGrow: 1, + }), + button: css({ + flexGrow: 1, + }), + }; const handleSave = () => { onSave(sortBy, sortOrder); }; @@ -98,8 +99,11 @@ const ConfigurationDialog = ({ {/* Configure how you want your list to be displayed. */} -
- + + {t('Sort By')} - + {t('Sort Direction')} -
- +
+ Language
); -}; +} export default LoginView; diff --git a/packages/web/src/components/PicturesAppBar.tsx b/packages/web/src/components/PicturesAppBar.tsx index d050099..0fb45cc 100644 --- a/packages/web/src/components/PicturesAppBar.tsx +++ b/packages/web/src/components/PicturesAppBar.tsx @@ -1,4 +1,5 @@ -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'; +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; import React from 'react'; import { AppBar, @@ -8,63 +9,25 @@ import { Toolbar, Typography, useScrollTrigger, -} from '@material-ui/core'; +} from '@mui/material'; import { useTranslation } from 'react-i18next'; -const useStyles = makeStyles((theme: Theme) => createStyles({ - root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - titleBar: { - background: - 'linear-gradient(to bottom, rgba(0,0,0,0) 0%, ' - + 'rgba(0,0,0,0) 70%, rgba(0,0,0,0) 100%)', - transition: 'background 2s ease-out', - '&:hover': { - background: - 'linear-gradient(to bottom, rgba(0,0,0,0) 0%, ' - + 'rgba(0,0,0,0) 70%, rgba(0,0,0,0) 100%)', - }, - }, - icon: { - color: 'white', - filter: 'drop-shadow(2px 4px 3px #222222)', - }, - listItem: { - cursor: 'pointer', - '&:hover': { - opacity: '0.9', - }, - }, - dialogImage: { - maxHeight: '80vh', - }, - loader: { - margin: '1rem', - }, - toolbarTitle: { - flexGrow: 1, - textAlign: 'left', - }, - toolbarButton: { - flexGrow: 1, - }, -})); - -const PicturesAppBar = ( - { onUploadClick, onSettingsClick, onLogoutClick }: - { - onUploadClick: () => void; - onSettingsClick: () => void; - onLogoutClick: () => void; - }, -) => { - const classes = useStyles(); +function PicturesAppBar({ onUploadClick, onSettingsClick, onLogoutClick }: +{ + onUploadClick: () => void; + onSettingsClick: () => void; + onLogoutClick: () => void; +}) { const trigger = useScrollTrigger(); + const styles = { + toolbarTitle: css({ + flexGrow: 1, + textAlign: 'left', + }), + toolbarButton: css({ + flexGrow: 1, + }), + }; const { t } = useTranslation(); return ( <> @@ -72,27 +35,24 @@ const PicturesAppBar = ( {/* - - */} - + edge="start" + color="inherit" + aria-label="menu" + onClick={onDrawer} + > + + */} + {t('Pictures')} - + cloud_upload settings @@ -105,6 +65,6 @@ const PicturesAppBar = ( ); -}; +} export default PicturesAppBar; diff --git a/packages/web/src/components/UploadDialog.tsx b/packages/web/src/components/UploadDialog.tsx index dfbd847..7500fb8 100644 --- a/packages/web/src/components/UploadDialog.tsx +++ b/packages/web/src/components/UploadDialog.tsx @@ -1,56 +1,55 @@ /* eslint-disable react/jsx-props-no-spreading */ +/** @jsxImportSource @emotion/react */ import React from 'react'; import { - createStyles, - Dialog, - DialogTitle, - IconButton, - makeStyles, - Theme, -} from '@material-ui/core'; + Dialog, DialogTitle, IconButton, Theme, +} from '@mui/material'; +import { css } from '@emotion/react'; import { useDropzone } from 'react-dropzone'; import { useTranslation } from 'react-i18next'; +import { useTheme } from '@mui/styles'; -const useStyles = makeStyles((theme: Theme) => createStyles({ - dropzone: { - textAlign: 'center', - padding: '20px', - border: '3px dashed #eeeeee', - backgroundColor: '#fafafa', - color: '#bdbdbd', - marginBottom: '20px', - marginLeft: '20px', - marginRight: '20px', - height: '20vh', - minWidth: '40vw', - transition: 'border-color 0.4s cubic-bezier(0.22, 1, 0.36, 1)', - }, - icon: { - fontSize: '2rem', - }, - accept: { - borderColor: 'green !important', - }, - reject: { - borderColor: 'red !important', - }, - closeButton: { - position: 'absolute', - right: theme.spacing(1), - top: theme.spacing(1), - color: theme.palette.grey[500], - }, -})); -const UploadDialog = ({ +function UploadDialog({ isOpen, onClose, onDrop, accept, }:{ isOpen: boolean; onClose: () => void; onDrop: (files: File[]) => void; accept: string[]; -}) => { - const classes = useStyles(); +}) { + const theme: Theme = useTheme(); + const styles = { + dropzone: css({ + textAlign: 'center', + padding: '20px', + border: '3px dashed #eeeeee', + backgroundColor: '#fafafa', + color: '#bdbdbd', + marginBottom: '20px', + marginLeft: '20px', + marginRight: '20px', + height: '20vh', + minWidth: '40vw', + transition: 'border-color 0.4s cubic-bezier(0.22, 1, 0.36, 1)', + }), + icon: css({ + fontSize: '2rem', + }), + accept: css({ + borderColor: 'green !important', + }), + reject: css({ + borderColor: 'red !important', + }), + closeButton: css({ + position: 'absolute', + right: theme.spacing(1), + top: theme.spacing(1), + color: theme.palette.grey[500], + }), + }; const { t } = useTranslation(); + const { getRootProps, getInputProps, @@ -74,8 +73,9 @@ const UploadDialog = ({ {t('Upload')} close @@ -83,13 +83,15 @@ const UploadDialog = ({
- + {isDragActive ? null : '📁'} {isDragAccept ? '📂' : null} {isDragReject ? '❌' : null} @@ -99,6 +101,6 @@ const UploadDialog = ({
); -}; +} export default UploadDialog; diff --git a/packages/web/src/i18n.ts b/packages/web/src/i18n.ts index abe0e98..1860e9c 100644 --- a/packages/web/src/i18n.ts +++ b/packages/web/src/i18n.ts @@ -19,7 +19,8 @@ i18n react: { useSuspense: false, }, - }); + }) + .catch((e) => { console.error(e); }); export const availableLanguages = [ { diff --git a/packages/web/src/index.tsx b/packages/web/src/index.tsx index 0c6628d..3a638be 100644 --- a/packages/web/src/index.tsx +++ b/packages/web/src/index.tsx @@ -1,6 +1,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import CssBaseline from '@material-ui/core/CssBaseline'; +import CssBaseline from '@mui/material/CssBaseline'; +import { ThemeProvider, createTheme, Theme } from '@mui/material/styles'; + import App from './App'; import reportWebVitals from './reportWebVitals'; import '@fontsource/roboto/300.css'; @@ -16,11 +18,26 @@ import './icons/icons.css'; import * as serviceWorkerRegistration from './serviceWorkerRegistration'; import './i18n'; +declare module '@mui/styles/defaultTheme' { + type DefaultTheme = Theme; +} serviceWorkerRegistration.register(); +const theme = createTheme({ + palette: { + primary: { + light: '#757ce8', + main: '#3f50b5', + dark: '#002884', + contrastText: '#fff', + }, + }, +}); ReactDOM.render( - + + + , document.getElementById('root'), diff --git a/packages/web/src/reportWebVitals.ts b/packages/web/src/reportWebVitals.ts index 107b6c1..2048321 100644 --- a/packages/web/src/reportWebVitals.ts +++ b/packages/web/src/reportWebVitals.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ import { ReportHandler } from 'web-vitals'; const reportWebVitals = (onPerfEntry?: ReportHandler) => { diff --git a/packages/web/src/service-worker.ts b/packages/web/src/service-worker.ts index 35bcb2f..4d47cf5 100644 --- a/packages/web/src/service-worker.ts +++ b/packages/web/src/service-worker.ts @@ -1,6 +1,9 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-floating-promises */ /* eslint-disable no-underscore-dangle */ -/// /* eslint-disable no-restricted-globals */ +/// // This service worker can be customized! // See https://developers.google.com/web/tools/workbox/modules @@ -27,7 +30,7 @@ precacheAndRoute(self.__WB_MANIFEST); // Set up App Shell-style routing, so that all navigation requests // are fulfilled with your index.html shell. Learn more at // https://developers.google.com/web/fundamentals/architecture/app-shell -const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$'); +const fileExtensionRegexp = /\/[^/?]+\.[^/]+$/; registerRoute( // Return false to exempt requests from being fulfilled by index.html. ({ request, url }: { request: Request; url: URL }) => { @@ -64,7 +67,7 @@ registerRoute( ); registerRoute( - new RegExp('https?:\\/\\/localhost:3002\\/\\w+\\.\\w+$'), + ({ url }) => /^\/\w+\.(mp4|webm|png|webp|gif|avif|jpeg|jpg)/gm.test(url.pathname), new CacheFirst({ cacheName: 'fulls', plugins: [ diff --git a/packages/web/src/serviceWorkerRegistration.ts b/packages/web/src/serviceWorkerRegistration.ts index 4fb8c48..bcd8d0f 100644 --- a/packages/web/src/serviceWorkerRegistration.ts +++ b/packages/web/src/serviceWorkerRegistration.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ /* eslint-disable @typescript-eslint/no-use-before-define */ // This optional code is used to register a service worker. // register() is not called by default. @@ -138,7 +139,7 @@ export function unregister() { registration.unregister(); }) .catch((error) => { - console.error(error.message); + console.error(error); }); } } diff --git a/packages/web/src/services/common.ts b/packages/web/src/services/common.ts new file mode 100644 index 0000000..845beb4 --- /dev/null +++ b/packages/web/src/services/common.ts @@ -0,0 +1,4 @@ +// eslint-disable-next-line import/prefer-default-export +export const hasKey = ( + k: K, o: T, +): o is T & Record => k in o; diff --git a/packages/web/src/services/images.ts b/packages/web/src/services/images.ts index 31ed04c..03c126d 100644 --- a/packages/web/src/services/images.ts +++ b/packages/web/src/services/images.ts @@ -3,13 +3,16 @@ import { Image, SortBy, SortOrder, Thumbnail, } from '../types'; import { API_BASE_URL } from '../consts'; +import { hasKey } from './common'; // Type guards -const isThumbnail = (thumb: any): thumb is Thumbnail => { +const isThumbnail = (thumb: unknown): thumb is Thumbnail => { if ( - 'url' in thumb + typeof thumb === 'object' + && thumb !== null + && hasKey('url', thumb) && typeof thumb.url === 'string' - && 'filetype' in thumb + && hasKey('filetype', thumb) && typeof thumb.filetype === 'string' ) { return true; @@ -17,17 +20,19 @@ const isThumbnail = (thumb: any): thumb is Thumbnail => { return false; }; -const isThumbnailArray = (thumbnails: any): thumbnails is Thumbnail[] => ( +const isThumbnailArray = (thumbnails: unknown): thumbnails is Thumbnail[] => ( Array.isArray(thumbnails) && thumbnails.every(isThumbnail) ); -const isImage = (image: any): image is Image => { +const isImage = (image: unknown): image is Image => { if ( - 'url' in image + typeof image === 'object' + && image !== null + && hasKey('url', image) && typeof image.url === 'string' - && 'filename' in image + && hasKey('filename', image) && typeof image.url === 'string' - && 'thumbnails' in image + && hasKey('thumbnails', image) && isThumbnailArray(image.thumbnails) ) { return true; @@ -35,7 +40,7 @@ const isImage = (image: any): image is Image => { return false; }; -const isImageArray = (images: any): images is Image[] => ( +const isImageArray = (images: unknown): images is Image[] => ( Array.isArray(images) && images.every(isImage) ); @@ -47,16 +52,16 @@ const isImageArray = (images: any): images is Image[] => ( * @return List of images */ export const getPage = async ( - page: number = 0, + page = 0, sortBy: SortBy = SortBy.Date, sortOrder: SortOrder = SortOrder.Descending, ): Promise => { - const { data } = await axios.get(`${API_BASE_URL}/images`, { + const response = await axios.get(`${API_BASE_URL}/images`, { params: { page, sortBy, sortOrder }, timeout: 5000, }); - if (isImageArray(data)) { - return data; + if (isImageArray(response?.data)) { + return response.data; } throw new Error('Malformed response from server'); }; @@ -70,14 +75,14 @@ export const getPage = async ( export const uploadImage = async (image: File): Promise => { const formData = new FormData(); formData.append('file', image); - const { data } = await axios.post(`${API_BASE_URL}/images`, formData, { + const response = await axios.post(`${API_BASE_URL}/images`, formData, { headers: { 'Content-Type': 'multipart/form-data', }, timeout: 10000, }); - if (isImage(data)) { - return data; + if (isImage(response?.data)) { + return response.data; } throw new Error('Malformed response from server'); }; diff --git a/packages/web/src/services/login.ts b/packages/web/src/services/login.ts index c10a1bf..85960d1 100644 --- a/packages/web/src/services/login.ts +++ b/packages/web/src/services/login.ts @@ -23,9 +23,12 @@ export const doLogin = async ( }, ); return status; - } catch (e: any) { - console.error(e); - return e.response.status || 500; + } catch (e) { + if (axios.isAxiosError(e)) { + console.error(e); + return e?.response?.status || 500; + } + return 500; } }; @@ -45,9 +48,12 @@ export const doRegister = async ( }, ); return status; - } catch (e: any) { - console.error(e); - return e.response.status || 500; + } catch (e) { + if (axios.isAxiosError(e)) { + console.error(e); + return e?.response?.status || 500; + } + return 500; } }; diff --git a/packages/web/src/services/meta.ts b/packages/web/src/services/meta.ts index 8873048..c156898 100644 --- a/packages/web/src/services/meta.ts +++ b/packages/web/src/services/meta.ts @@ -1,16 +1,23 @@ import axios from 'axios'; import { API_BASE_URL } from '../consts'; import { Meta } from '../types'; +import { hasKey } from './common'; + +const isMeta = (data: unknown): data is Meta => typeof data === 'object' + && data != null + && hasKey('accepted', data) + && Array.isArray(data.accepted) + && data.accepted.every((x: unknown): x is string => typeof x === 'string') + && hasKey('setupFinished', data) + && typeof data.setupFinished === 'boolean'; // eslint-disable-next-line import/prefer-default-export export const getMeta = async (): Promise => { - const { data } = await axios.get(`${API_BASE_URL}/meta`); + const response = await axios.get(`${API_BASE_URL}/meta`); if ( - Array.isArray(data.accepted) - && data.accepted.every((x: any): x is string => typeof x === 'string') - && typeof data.setupFinished === 'boolean' + isMeta(response.data) ) { - return { accepted: data.accepted, setupFinished: data.setupFinished }; + return response.data; } throw new Error('Malformed server response'); }; diff --git a/packages/web/src/services/settings.ts b/packages/web/src/services/settings.ts index 594e670..06ded17 100644 --- a/packages/web/src/services/settings.ts +++ b/packages/web/src/services/settings.ts @@ -17,6 +17,7 @@ export const getUserState = (): boolean => { if (serializedUserState === null) { return false; } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const userState = JSON.parse(serializedUserState); if (typeof userState !== 'boolean') { return false; diff --git a/packages/web/src/services/user.ts b/packages/web/src/services/user.ts index 6d35ab8..1a3008a 100644 --- a/packages/web/src/services/user.ts +++ b/packages/web/src/services/user.ts @@ -1,20 +1,35 @@ import axios from 'axios'; import { API_BASE_URL } from '../consts'; +import { hasKey } from './common'; + +const isApiToken = (data: unknown): data is { + token: string +} => typeof data === 'object' + && data != null + && hasKey('token', data) + && typeof data.token === 'string'; export const getApiKey = async (): Promise => { - const { data } = await axios.post(`${API_BASE_URL}/user/getApiKey`); - if (typeof data?.token === 'string') { - return data.token; + const response = await axios.post(`${API_BASE_URL}/user/getApiKey`); + if (isApiToken(response.data)) { + return response.data.token; } throw new Error('Malformed server response'); }; +const isStatus = (data: unknown): data is { + status: string +} => typeof data === 'object' + && data != null + && hasKey('status', data) + && typeof data.status === 'string'; + export const updateCredentials = async ( oldPassword: string, username: string, password: string, ) => { - const { data } = await axios.post( + const response = await axios.post( `${API_BASE_URL}/user/updateCredentials`, { ...(username !== '' ? { username } : {}), @@ -23,7 +38,7 @@ export const updateCredentials = async ( }, {}, ); - if (data.status !== 'success') { + if (!isStatus(response.data) || response.data.status !== 'success') { throw new Error('Malformed server response'); } }; diff --git a/yarn.lock b/yarn.lock index 130eebe..9b9f747 100644 --- a/yarn.lock +++ b/yarn.lock @@ -723,7 +723,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.17.12": +"@babel/plugin-syntax-jsx@npm:^7.12.13, @babel/plugin-syntax-jsx@npm:^7.17.12": version: 7.17.12 resolution: "@babel/plugin-syntax-jsx@npm:7.17.12" dependencies: @@ -1453,7 +1453,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.18.3 resolution: "@babel/runtime@npm:7.18.3" dependencies: @@ -1527,6 +1527,15 @@ __metadata: languageName: node linkType: hard +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" + dependencies: + "@jridgewell/trace-mapping": 0.3.9 + checksum: 5718f267085ed8edb3e7ef210137241775e607ee18b77d95aa5bd7514f47f5019aa2d82d96b3bf342ef7aa890a346fa1044532ff7cc3009e7d24fce3ce6200fa + languageName: node + linkType: hard + "@csstools/normalize.css@npm:*": version: 12.0.0 resolution: "@csstools/normalize.css@npm:12.0.0" @@ -1690,6 +1699,41 @@ __metadata: languageName: node linkType: hard +"@emotion/babel-plugin@npm:^11.7.1": + version: 11.9.2 + resolution: "@emotion/babel-plugin@npm:11.9.2" + dependencies: + "@babel/helper-module-imports": ^7.12.13 + "@babel/plugin-syntax-jsx": ^7.12.13 + "@babel/runtime": ^7.13.10 + "@emotion/hash": ^0.8.0 + "@emotion/memoize": ^0.7.5 + "@emotion/serialize": ^1.0.2 + babel-plugin-macros: ^2.6.1 + convert-source-map: ^1.5.0 + escape-string-regexp: ^4.0.0 + find-root: ^1.1.0 + source-map: ^0.5.7 + stylis: 4.0.13 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 2d2c4fadd389862896bcbc5f42c9b9c1a199810173fcf14e5520506c7179c2ddb991b8832fd273f42104cf0dae98886ad8e767b5e38ad235b652d903c3b8a328 + languageName: node + linkType: hard + +"@emotion/cache@npm:^11.7.1": + version: 11.7.1 + resolution: "@emotion/cache@npm:11.7.1" + dependencies: + "@emotion/memoize": ^0.7.4 + "@emotion/sheet": ^1.1.0 + "@emotion/utils": ^1.0.0 + "@emotion/weak-memoize": ^0.2.5 + stylis: 4.0.13 + checksum: cf7aa8fe3bacfdedcda94b53e76a7635e122043439715fcfbf7f1a81340cfe6099a59134481a03ec3e0437466566d18528577d1e6ea92f5b98c372b8b38a8f35 + languageName: node + linkType: hard + "@emotion/hash@npm:^0.8.0": version: 0.8.0 resolution: "@emotion/hash@npm:0.8.0" @@ -1697,6 +1741,108 @@ __metadata: languageName: node linkType: hard +"@emotion/is-prop-valid@npm:^1.1.2": + version: 1.1.2 + resolution: "@emotion/is-prop-valid@npm:1.1.2" + dependencies: + "@emotion/memoize": ^0.7.4 + checksum: 58b1f2d429a589f8f5bc2c33a8732cbb7bbcb17131a103511ef9a94ac754d7eeb53d627f947da480cd977f9d419fd92e244991680292f3287204159652745707 + languageName: node + linkType: hard + +"@emotion/memoize@npm:^0.7.4, @emotion/memoize@npm:^0.7.5": + version: 0.7.5 + resolution: "@emotion/memoize@npm:0.7.5" + checksum: 83da8d4a7649a92c72f960817692bc6be13cc13e107b9f7e878d63766525ed4402881bfeb3cda61145c050281e7e260f114a0a2870515527346f2ef896b915b3 + languageName: node + linkType: hard + +"@emotion/react@npm:^11.9.0": + version: 11.9.0 + resolution: "@emotion/react@npm:11.9.0" + dependencies: + "@babel/runtime": ^7.13.10 + "@emotion/babel-plugin": ^11.7.1 + "@emotion/cache": ^11.7.1 + "@emotion/serialize": ^1.0.3 + "@emotion/utils": ^1.1.0 + "@emotion/weak-memoize": ^0.2.5 + hoist-non-react-statics: ^3.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + react: ">=16.8.0" + peerDependenciesMeta: + "@babel/core": + optional: true + "@types/react": + optional: true + checksum: 4ceb004f942fb7557a55ea17aad2c48c4cd48ed5a780ccdc2993e4bded2f94d7c1764bd2f4fbe53f5b26059263599cec64ff66d29447e281a58c60b39c72e5cc + languageName: node + linkType: hard + +"@emotion/serialize@npm:^1.0.2, @emotion/serialize@npm:^1.0.3": + version: 1.0.3 + resolution: "@emotion/serialize@npm:1.0.3" + dependencies: + "@emotion/hash": ^0.8.0 + "@emotion/memoize": ^0.7.4 + "@emotion/unitless": ^0.7.5 + "@emotion/utils": ^1.0.0 + csstype: ^3.0.2 + checksum: 99a9053bd98c99d63af542ebee029281eeaf653e3a12e97ee79bad7330c68408104c30be6fc07a528e38bb69aba680655181744b76ec6c6f459c121cb805fac2 + languageName: node + linkType: hard + +"@emotion/sheet@npm:^1.1.0": + version: 1.1.0 + resolution: "@emotion/sheet@npm:1.1.0" + checksum: a4b74e16a8fea1157413efe4904f5f679d724323cb605d66d20a0b98744422f5d411fca927ceb52e4de454a0a819c5273ca9496db9f011b4ecd17b9f1b212007 + languageName: node + linkType: hard + +"@emotion/styled@npm:^11.8.1": + version: 11.8.1 + resolution: "@emotion/styled@npm:11.8.1" + dependencies: + "@babel/runtime": ^7.13.10 + "@emotion/babel-plugin": ^11.7.1 + "@emotion/is-prop-valid": ^1.1.2 + "@emotion/serialize": ^1.0.2 + "@emotion/utils": ^1.1.0 + peerDependencies: + "@babel/core": ^7.0.0 + "@emotion/react": ^11.0.0-rc.0 + react: ">=16.8.0" + peerDependenciesMeta: + "@babel/core": + optional: true + "@types/react": + optional: true + checksum: 67150fa788785c34e285b90acecc91fe7a63babceaefbeffd053bed0fa31f72a05bfeeb9d15620766e543e007b9ccac2e836812eec2e791f962ec4e52731ae4c + languageName: node + linkType: hard + +"@emotion/unitless@npm:^0.7.5": + version: 0.7.5 + resolution: "@emotion/unitless@npm:0.7.5" + checksum: f976e5345b53fae9414a7b2e7a949aa6b52f8bdbcc84458b1ddc0729e77ba1d1dfdff9960e0da60183877873d3a631fa24d9695dd714ed94bcd3ba5196586a6b + languageName: node + linkType: hard + +"@emotion/utils@npm:^1.0.0, @emotion/utils@npm:^1.1.0": + version: 1.1.0 + resolution: "@emotion/utils@npm:1.1.0" + checksum: d3b681ca3a23b07033ac6c6937e71010a5549ac8ccec325eb6c91a7e48d9a73db83fa5dadc58be981bb125d7c00fedca868ea4362b1da9e02866615f96be4df1 + languageName: node + linkType: hard + +"@emotion/weak-memoize@npm:^0.2.5": + version: 0.2.5 + resolution: "@emotion/weak-memoize@npm:0.2.5" + checksum: 27d402b0c683b94658220b6d47840346ee582329ca2a15ec9c233492e0f1a27687ccb233b76eedc922f2e185e444cc89f7b97a81a1d3e5ae9f075bab08e965ea + languageName: node + linkType: hard + "@eslint/eslintrc@npm:^0.4.3": version: 0.4.3 resolution: "@eslint/eslintrc@npm:0.4.3" @@ -2291,6 +2437,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" + dependencies: + "@jridgewell/resolve-uri": ^3.0.3 + "@jridgewell/sourcemap-codec": ^1.4.10 + checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:^0.3.7, @jridgewell/trace-mapping@npm:^0.3.9": version: 0.3.13 resolution: "@jridgewell/trace-mapping@npm:0.3.13" @@ -2308,106 +2464,182 @@ __metadata: languageName: node linkType: hard -"@material-ui/core@npm:^4.11.3": - version: 4.12.4 - resolution: "@material-ui/core@npm:4.12.4" +"@mui/base@npm:5.0.0-alpha.83": + version: 5.0.0-alpha.83 + resolution: "@mui/base@npm:5.0.0-alpha.83" dependencies: - "@babel/runtime": ^7.4.4 - "@material-ui/styles": ^4.11.5 - "@material-ui/system": ^4.12.2 - "@material-ui/types": 5.1.0 - "@material-ui/utils": ^4.11.3 - "@types/react-transition-group": ^4.2.0 - clsx: ^1.0.4 - hoist-non-react-statics: ^3.3.2 - popper.js: 1.16.1-lts - prop-types: ^15.7.2 - react-is: ^16.8.0 || ^17.0.0 - react-transition-group: ^4.4.0 + "@babel/runtime": ^7.17.2 + "@emotion/is-prop-valid": ^1.1.2 + "@mui/types": ^7.1.3 + "@mui/utils": ^5.8.0 + "@popperjs/core": ^2.11.5 + clsx: ^1.1.1 + prop-types: ^15.8.1 + react-is: ^17.0.2 peerDependencies: - "@types/react": ^16.8.6 || ^17.0.0 - react: ^16.8.0 || ^17.0.0 - react-dom: ^16.8.0 || ^17.0.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 96b48deccda87ced841b1db45bed2be6d2b6d1b4eae72cd5c9b931201cb72026330688e0fead54e715bcead40b267ea88bde781c9f1563b1a71a5c51bf187289 + checksum: 0ad413a8da41dd09b018bb4c7961c5937f68e2656b56d4d9ecadc49c3c43a3d7974a52be9fe015df1f8381864fa8eefb98c8599deed991a4741c6287145a1da9 languageName: node linkType: hard -"@material-ui/styles@npm:^4.11.5": - version: 4.11.5 - resolution: "@material-ui/styles@npm:4.11.5" +"@mui/material@npm:^5.8.2": + version: 5.8.2 + resolution: "@mui/material@npm:5.8.2" dependencies: - "@babel/runtime": ^7.4.4 + "@babel/runtime": ^7.17.2 + "@mui/base": 5.0.0-alpha.83 + "@mui/system": ^5.8.2 + "@mui/types": ^7.1.3 + "@mui/utils": ^5.8.0 + "@types/react-transition-group": ^4.4.4 + clsx: ^1.1.1 + csstype: ^3.1.0 + hoist-non-react-statics: ^3.3.2 + prop-types: ^15.8.1 + react-is: ^17.0.2 + react-transition-group: ^4.4.2 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: 2957cb50478099579f83b187df6faaaf4dc794b7948bdb5263bee68ce005f1037b6a6b78420e60dbacf6911c616601337ca884e118804753d15fbea6364c5626 + languageName: node + linkType: hard + +"@mui/private-theming@npm:^5.8.0": + version: 5.8.0 + resolution: "@mui/private-theming@npm:5.8.0" + dependencies: + "@babel/runtime": ^7.17.2 + "@mui/utils": ^5.8.0 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 6107b579409913a5e0d6d79fbe074ae4ad55e57f7a485da4542a5772be86b835994311609e84e4e881ea187c5b8892e432bcce9ac98d4e69dd7ace55da675f8a + languageName: node + linkType: hard + +"@mui/styled-engine@npm:^5.8.0": + version: 5.8.0 + resolution: "@mui/styled-engine@npm:5.8.0" + dependencies: + "@babel/runtime": ^7.17.2 + "@emotion/cache": ^11.7.1 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.4.1 + "@emotion/styled": ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + checksum: f1140151cb06b72af774e6c14f537879bee0e699fff05cac5f9b1e4483d5202e161dc6d8e23ff7e31e3f660867056689b2225ab1d7ad69f45dc489d9ed058a92 + languageName: node + linkType: hard + +"@mui/styles@npm:^5.8.0": + version: 5.8.0 + resolution: "@mui/styles@npm:5.8.0" + dependencies: + "@babel/runtime": ^7.17.2 "@emotion/hash": ^0.8.0 - "@material-ui/types": 5.1.0 - "@material-ui/utils": ^4.11.3 - clsx: ^1.0.4 - csstype: ^2.5.2 + "@mui/private-theming": ^5.8.0 + "@mui/types": ^7.1.3 + "@mui/utils": ^5.8.0 + clsx: ^1.1.1 + csstype: ^3.0.11 hoist-non-react-statics: ^3.3.2 - jss: ^10.5.1 - jss-plugin-camel-case: ^10.5.1 - jss-plugin-default-unit: ^10.5.1 - jss-plugin-global: ^10.5.1 - jss-plugin-nested: ^10.5.1 - jss-plugin-props-sort: ^10.5.1 - jss-plugin-rule-value-function: ^10.5.1 - jss-plugin-vendor-prefixer: ^10.5.1 - prop-types: ^15.7.2 + jss: ^10.8.2 + jss-plugin-camel-case: ^10.8.2 + jss-plugin-default-unit: ^10.8.2 + jss-plugin-global: ^10.8.2 + jss-plugin-nested: ^10.8.2 + jss-plugin-props-sort: ^10.8.2 + jss-plugin-rule-value-function: ^10.8.2 + jss-plugin-vendor-prefixer: ^10.8.2 + prop-types: ^15.8.1 peerDependencies: - "@types/react": ^16.8.6 || ^17.0.0 - react: ^16.8.0 || ^17.0.0 - react-dom: ^16.8.0 || ^17.0.0 + "@types/react": ^17.0.0 + react: ^17.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: dbf3985ef57c1b7dae3fd916d5bfd61f2097afb93c9e1f64832cfcb8fc9bbf38a504c9632ed7b76eb5d235670083d9e66d35942bc976b7cd148c71d75b808e82 + checksum: 5c14a9ef6319f008ac6fc20bc5f7a50e20258e29bcce15f4c6224e3248b9bfe4dae52798390b3c8aae98c4ddbec9814df87f942c5e1a8dd1809b0eaf55ab5e37 languageName: node linkType: hard -"@material-ui/system@npm:^4.12.2": - version: 4.12.2 - resolution: "@material-ui/system@npm:4.12.2" +"@mui/system@npm:^5.8.2": + version: 5.8.2 + resolution: "@mui/system@npm:5.8.2" dependencies: - "@babel/runtime": ^7.4.4 - "@material-ui/utils": ^4.11.3 - csstype: ^2.5.2 - prop-types: ^15.7.2 + "@babel/runtime": ^7.17.2 + "@mui/private-theming": ^5.8.0 + "@mui/styled-engine": ^5.8.0 + "@mui/types": ^7.1.3 + "@mui/utils": ^5.8.0 + clsx: ^1.1.1 + csstype: ^3.1.0 + prop-types: ^15.8.1 peerDependencies: - "@types/react": ^16.8.6 || ^17.0.0 - react: ^16.8.0 || ^17.0.0 - react-dom: ^16.8.0 || ^17.0.0 + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true "@types/react": optional: true - checksum: ebe6b3cc5f111034eacd763014f3260f7647b5e0cd132870f2ee18855cf3d51a996b4633035fe6f5f8965489944db4ac0cb3b71b84a765faa35a6861532ac9f6 + checksum: 1d968620bbca0663308b6940252311dcb1c591a0f94a8ad112252d404e2ff52c9eb343a475e32b2bf5ac1ae3b56f349c1ef2a165b60158b8ea752a177acefea6 languageName: node linkType: hard -"@material-ui/types@npm:5.1.0": - version: 5.1.0 - resolution: "@material-ui/types@npm:5.1.0" +"@mui/types@npm:^7.1.3": + version: 7.1.3 + resolution: "@mui/types@npm:7.1.3" peerDependencies: "@types/react": "*" peerDependenciesMeta: "@types/react": optional: true - checksum: 64ac0938ee6f48011ba596f7422ab0660d9a8d9b4f5f183b39bd63185b1ce724209f65580f0af686d59b524603ffa57418ca2d443b69bec894303f80779c61f8 + checksum: 4990f505f1058bdd4c01ea21a6a6f788e5d3ff73b50962879d33bbf9c98ef1f18d8b6664025ce1dbd42544a79d7697d0011834f8fd83d12c9705f2c702829bb4 languageName: node linkType: hard -"@material-ui/utils@npm:^4.11.3": - version: 4.11.3 - resolution: "@material-ui/utils@npm:4.11.3" +"@mui/utils@npm:^5.8.0": + version: 5.8.0 + resolution: "@mui/utils@npm:5.8.0" dependencies: - "@babel/runtime": ^7.4.4 - prop-types: ^15.7.2 - react-is: ^16.8.0 || ^17.0.0 + "@babel/runtime": ^7.17.2 + "@types/prop-types": ^15.7.5 + "@types/react-is": ^16.7.1 || ^17.0.0 + prop-types: ^15.8.1 + react-is: ^17.0.2 peerDependencies: - react: ^16.8.0 || ^17.0.0 - react-dom: ^16.8.0 || ^17.0.0 - checksum: 05ff67c982b33d3b4260cfaeaf566f3ccaecaebb231907ed626bcc30322d89d705bfe79b8805c0dda2f1dc2cfa98ca9d731ec8ae12868da7a98568a41c7dc231 + react: ^17.0.0 || ^18.0.0 + checksum: 488b4e709e3f86e7a627f2e61b4c8b3d6fcb606922666b829f5a24c77383ee5776446a30e7b5c10007d03e4e764c3190d608485113d5108e54f79308bddafefc languageName: node linkType: hard @@ -2497,6 +2729,13 @@ __metadata: languageName: node linkType: hard +"@popperjs/core@npm:^2.11.5": + version: 2.11.5 + resolution: "@popperjs/core@npm:2.11.5" + checksum: fd7f9dca3fb716d7426332b6ee283f88d2724c0ab342fb678865a640bad403dfb9eeebd8204a406986162f7e2b33394f104320008b74d0e9066d7322f70ea35d + languageName: node + linkType: hard + "@rollup/plugin-babel@npm:^5.2.0": version: 5.3.1 resolution: "@rollup/plugin-babel@npm:5.3.1" @@ -2824,6 +3063,34 @@ __metadata: languageName: node linkType: hard +"@tsconfig/node10@npm:^1.0.7": + version: 1.0.8 + resolution: "@tsconfig/node10@npm:1.0.8" + checksum: b8d5fffbc6b17ef64ef74f7fdbccee02a809a063ade785c3648dae59406bc207f70ea2c4296f92749b33019fa36a5ae716e42e49cc7f1bbf0fd147be0d6b970a + languageName: node + linkType: hard + +"@tsconfig/node12@npm:^1.0.7": + version: 1.0.9 + resolution: "@tsconfig/node12@npm:1.0.9" + checksum: a01b2400ab3582b86b589c6d31dcd0c0656f333adecde85d6d7d4086adb059808b82692380bb169546d189bf771ae21d02544a75b57bd6da4a5dd95f8567bec9 + languageName: node + linkType: hard + +"@tsconfig/node14@npm:^1.0.0": + version: 1.0.1 + resolution: "@tsconfig/node14@npm:1.0.1" + checksum: 976345e896c0f059867f94f8d0f6ddb8b1844fb62bf36b727de8a9a68f024857e5db97ed51d3325e23e0616a5e48c034ff51a8d595b3fe7e955f3587540489be + languageName: node + linkType: hard + +"@tsconfig/node16@npm:^1.0.2": + version: 1.0.2 + resolution: "@tsconfig/node16@npm:1.0.2" + checksum: ca94d3639714672bbfd55f03521d3f56bb6a25479bd425da81faf21f13e1e9d15f40f97377dedbbf477a5841c5b0c8f4cd1b391f33553d750b9202c54c2c07aa + languageName: node + linkType: hard + "@types/aria-query@npm:^4.2.0": version: 4.2.2 resolution: "@types/aria-query@npm:4.2.2" @@ -3252,7 +3519,7 @@ __metadata: languageName: node linkType: hard -"@types/prop-types@npm:*": +"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5": version: 15.7.5 resolution: "@types/prop-types@npm:15.7.5" checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 @@ -3298,7 +3565,16 @@ __metadata: languageName: node linkType: hard -"@types/react-transition-group@npm:^4.2.0": +"@types/react-is@npm:^16.7.1 || ^17.0.0": + version: 17.0.3 + resolution: "@types/react-is@npm:17.0.3" + dependencies: + "@types/react": "*" + checksum: 6abb7c47d54f012272650df8a962a28bd82f219291e5ef8b4dfa7fe0bb98ae243b060bf9fbe8ceff6213141794855a006db194b490b00ffd15842ae19d0ce1f0 + languageName: node + linkType: hard + +"@types/react-transition-group@npm:^4.4.4": version: 4.4.4 resolution: "@types/react-transition-group@npm:4.4.4" dependencies: @@ -3858,6 +4134,13 @@ __metadata: languageName: node linkType: hard +"acorn-walk@npm:^8.1.1": + version: 8.2.0 + resolution: "acorn-walk@npm:8.2.0" + checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 + languageName: node + linkType: hard + "acorn@npm:^7.0.0, acorn@npm:^7.1.1, acorn@npm:^7.4.0": version: 7.4.1 resolution: "acorn@npm:7.4.1" @@ -4455,6 +4738,17 @@ __metadata: languageName: node linkType: hard +"babel-plugin-macros@npm:^2.6.1": + version: 2.8.0 + resolution: "babel-plugin-macros@npm:2.8.0" + dependencies: + "@babel/runtime": ^7.7.2 + cosmiconfig: ^6.0.0 + resolve: ^1.12.0 + checksum: 59b09a21cf3ae1e14186c1b021917d004b49b953824b24953a54c6502da79e8051d4ac31cfd4a0ae7f6ea5ddf1f7edd93df4895dd3c3982a5b2431859c2889ac + languageName: node + linkType: hard + "babel-plugin-macros@npm:^3.1.0": version: 3.1.0 resolution: "babel-plugin-macros@npm:3.1.0" @@ -5215,7 +5509,7 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^1.0.4": +"clsx@npm:^1.1.1": version: 1.1.1 resolution: "clsx@npm:1.1.1" checksum: ff052650329773b9b245177305fc4c4dc3129f7b2be84af4f58dc5defa99538c61d4207be7419405a5f8f3d92007c954f4daba5a7b74e563d5de71c28c830063 @@ -5499,7 +5793,7 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": +"convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": version: 1.8.0 resolution: "convert-source-map@npm:1.8.0" dependencies: @@ -5977,14 +6271,7 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^2.5.2": - version: 2.6.20 - resolution: "csstype@npm:2.6.20" - checksum: cb5d5ded49c3390909e93b20b285d4a63d0ba5b10294bdfbc4cf911f80e91d6cf367ea671f99f09570762535c14ea7074a2c7fa73f02008203f01328dea8968b - languageName: node - linkType: hard - -"csstype@npm:^3.0.2": +"csstype@npm:^3.0.11, csstype@npm:^3.0.2, csstype@npm:^3.1.0": version: 3.1.0 resolution: "csstype@npm:3.1.0" checksum: 644e986cefab86525f0b674a06889cfdbb1f117e5b7d1ce0fc55b0423ecc58807a1ea42ecc75c4f18999d14fc42d1d255f84662a45003a52bb5840e977eb2ffd @@ -7666,6 +7953,13 @@ __metadata: languageName: node linkType: hard +"find-root@npm:^1.1.0": + version: 1.1.0 + resolution: "find-root@npm:1.1.0" + checksum: b2a59fe4b6c932eef36c45a048ae8f93c85640212ebe8363164814990ee20f154197505965f3f4f102efc33bfb1cbc26fd17c4a2fc739ebc51b886b137cbefaf + languageName: node + linkType: hard + "find-up@npm:^2.1.0": version: 2.1.0 resolution: "find-up@npm:2.1.0" @@ -8331,7 +8625,7 @@ __metadata: languageName: node linkType: hard -"hoist-non-react-statics@npm:^3.3.2": +"hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" dependencies: @@ -10469,7 +10763,7 @@ __metadata: languageName: node linkType: hard -"jss-plugin-camel-case@npm:^10.5.1": +"jss-plugin-camel-case@npm:^10.8.2": version: 10.9.0 resolution: "jss-plugin-camel-case@npm:10.9.0" dependencies: @@ -10480,7 +10774,7 @@ __metadata: languageName: node linkType: hard -"jss-plugin-default-unit@npm:^10.5.1": +"jss-plugin-default-unit@npm:^10.8.2": version: 10.9.0 resolution: "jss-plugin-default-unit@npm:10.9.0" dependencies: @@ -10490,7 +10784,7 @@ __metadata: languageName: node linkType: hard -"jss-plugin-global@npm:^10.5.1": +"jss-plugin-global@npm:^10.8.2": version: 10.9.0 resolution: "jss-plugin-global@npm:10.9.0" dependencies: @@ -10500,7 +10794,7 @@ __metadata: languageName: node linkType: hard -"jss-plugin-nested@npm:^10.5.1": +"jss-plugin-nested@npm:^10.8.2": version: 10.9.0 resolution: "jss-plugin-nested@npm:10.9.0" dependencies: @@ -10511,7 +10805,7 @@ __metadata: languageName: node linkType: hard -"jss-plugin-props-sort@npm:^10.5.1": +"jss-plugin-props-sort@npm:^10.8.2": version: 10.9.0 resolution: "jss-plugin-props-sort@npm:10.9.0" dependencies: @@ -10521,7 +10815,7 @@ __metadata: languageName: node linkType: hard -"jss-plugin-rule-value-function@npm:^10.5.1": +"jss-plugin-rule-value-function@npm:^10.8.2": version: 10.9.0 resolution: "jss-plugin-rule-value-function@npm:10.9.0" dependencies: @@ -10532,7 +10826,7 @@ __metadata: languageName: node linkType: hard -"jss-plugin-vendor-prefixer@npm:^10.5.1": +"jss-plugin-vendor-prefixer@npm:^10.8.2": version: 10.9.0 resolution: "jss-plugin-vendor-prefixer@npm:10.9.0" dependencies: @@ -10543,7 +10837,7 @@ __metadata: languageName: node linkType: hard -"jss@npm:10.9.0, jss@npm:^10.5.1": +"jss@npm:10.9.0, jss@npm:^10.8.2": version: 10.9.0 resolution: "jss@npm:10.9.0" dependencies: @@ -11164,7 +11458,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.1.1, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6": +"minimist@npm:^1.1.1, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.6": version: 1.2.6 resolution: "minimist@npm:1.2.6" checksum: d15428cd1e11eb14e1233bcfb88ae07ed7a147de251441d61158619dfb32c4d7e9061d09cab4825fdee18ecd6fce323228c8c47b5ba7cd20af378ca4048fb3fb @@ -12210,13 +12504,6 @@ __metadata: languageName: node linkType: hard -"popper.js@npm:1.16.1-lts": - version: 1.16.1-lts - resolution: "popper.js@npm:1.16.1-lts" - checksum: 27c00b5b07afa91a5e9f9db78a9a61b50f44ca156d09c851cd29d79cd359e54cfde4288ae555b88801438227e452e56cb4b56bd79fd45ab17dac780a70a7e9ac - languageName: node - linkType: hard - "posix-character-classes@npm:^0.1.0": version: 0.1.1 resolution: "posix-character-classes@npm:0.1.1" @@ -13185,7 +13472,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.5.8, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": +"prop-types@npm:^15.5.8, prop-types@npm:^15.6.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -13434,7 +13721,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.8.0 || ^17.0.0, react-is@npm:^17.0.1": +"react-is@npm:^17.0.1, react-is@npm:^17.0.2": version: 17.0.2 resolution: "react-is@npm:17.0.2" checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8 @@ -13522,7 +13809,7 @@ __metadata: languageName: node linkType: hard -"react-transition-group@npm:^4.4.0": +"react-transition-group@npm:^4.4.2": version: 4.4.2 resolution: "react-transition-group@npm:4.4.2" dependencies: @@ -13905,7 +14192,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.0.0, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.18.1, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.0": +"resolve@npm:^1.0.0, resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.14.2, resolve@npm:^1.18.1, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.0": version: 1.22.0 resolution: "resolve@npm:1.22.0" dependencies: @@ -13928,7 +14215,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.0.0#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.18.1#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.0#~builtin": +"resolve@patch:resolve@^1.0.0#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.18.1#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.0#~builtin": version: 1.22.0 resolution: "resolve@patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b" dependencies: @@ -14376,8 +14663,8 @@ __metadata: supertest: ^6.0.1 tmp: ^0.2.1 ts-jest: ^26.4.4 - ts-node: ^9.1.1 - ts-node-dev: ^1.1.1 + ts-node: ^10.8.1 + ts-node-dev: ^2.0.0 typescript: ^4.1.3 winston: ^3.3.3 languageName: unknown @@ -14681,7 +14968,7 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:^0.5.12, source-map-support@npm:^0.5.17, source-map-support@npm:^0.5.6, source-map-support@npm:~0.5.20": +"source-map-support@npm:^0.5.12, source-map-support@npm:^0.5.6, source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" dependencies: @@ -14705,7 +14992,7 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.5.6": +"source-map@npm:^0.5.6, source-map@npm:^0.5.7": version: 0.5.7 resolution: "source-map@npm:0.5.7" checksum: 5dc2043b93d2f194142c7f38f74a24670cd7a0063acdaf4bf01d2964b402257ae843c2a8fa822ad5b71013b5fcafa55af7421383da919752f22ff488bc553f4d @@ -15149,6 +15436,13 @@ __metadata: languageName: node linkType: hard +"stylis@npm:4.0.13": + version: 4.0.13 + resolution: "stylis@npm:4.0.13" + checksum: 8ea7a87028b6383c6a982231c4b5b6150031ce028e0fdaf7b2ace82253d28a8af50cc5a9da8a421d3c7c4441592f393086e332795add672aa4a825f0fe3713a3 + languageName: node + linkType: hard + "superagent@npm:^7.1.3": version: 7.1.6 resolution: "superagent@npm:7.1.6" @@ -15676,19 +15970,19 @@ __metadata: languageName: node linkType: hard -"ts-node-dev@npm:^1.1.1": - version: 1.1.8 - resolution: "ts-node-dev@npm:1.1.8" +"ts-node-dev@npm:^2.0.0": + version: 2.0.0 + resolution: "ts-node-dev@npm:2.0.0" dependencies: chokidar: ^3.5.1 dynamic-dedupe: ^0.3.0 - minimist: ^1.2.5 + minimist: ^1.2.6 mkdirp: ^1.0.4 resolve: ^1.0.0 rimraf: ^2.6.1 source-map-support: ^0.5.12 tree-kill: ^1.2.2 - ts-node: ^9.0.0 + ts-node: ^10.4.0 tsconfig: ^7.0.0 peerDependencies: node-notifier: "*" @@ -15699,28 +15993,45 @@ __metadata: bin: ts-node-dev: lib/bin.js tsnd: lib/bin.js - checksum: 768a5806215ca78694d39b85ec6877ba41d33b5affcbedc8208f0e4befd5ba1cffbcc505d5d8eca82ea23a4517a79be5f5de6350cb6e249425c832f4ddf10a0f + checksum: d654b401de3d13c167981481be2a375229f6bfd2aeedf43bc0b6816e57676fcbfba3afdcf209c7a06fb6bd8768ca548c2eb0a0c9d38fa42246be3f50df1b28fb languageName: node linkType: hard -"ts-node@npm:^9.0.0, ts-node@npm:^9.1.1": - version: 9.1.1 - resolution: "ts-node@npm:9.1.1" +"ts-node@npm:^10.4.0, ts-node@npm:^10.8.1": + version: 10.8.1 + resolution: "ts-node@npm:10.8.1" dependencies: + "@cspotcode/source-map-support": ^0.8.0 + "@tsconfig/node10": ^1.0.7 + "@tsconfig/node12": ^1.0.7 + "@tsconfig/node14": ^1.0.0 + "@tsconfig/node16": ^1.0.2 + acorn: ^8.4.1 + acorn-walk: ^8.1.1 arg: ^4.1.0 create-require: ^1.1.0 diff: ^4.0.1 make-error: ^1.1.1 - source-map-support: ^0.5.17 + v8-compile-cache-lib: ^3.0.1 yn: 3.1.1 peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true bin: ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js ts-node-script: dist/bin-script.js ts-node-transpile-only: dist/bin-transpile.js ts-script: dist/bin-script-deprecated.js - checksum: 356e2647b8b1e6ab00380c0537fa569b63bd9b6f006cc40fd650f81fae1817bd8fecc075300036950d8f45c1d85b95be33cd1e48a1a424a7d86c3dbb42bf60e5 + checksum: 7d1aa7aa3ae1c0459c4922ed0dbfbade442cfe0c25aebaf620cdf1774f112c8d7a9b14934cb6719274917f35b2c503ba87bcaf5e16a0d39ba0f68ce3e7728363 languageName: node linkType: hard @@ -16080,6 +16391,13 @@ __metadata: languageName: node linkType: hard +"v8-compile-cache-lib@npm:^3.0.1": + version: 3.0.1 + resolution: "v8-compile-cache-lib@npm:3.0.1" + checksum: 78089ad549e21bcdbfca10c08850022b22024cdcc2da9b168bcf5a73a6ed7bf01a9cebb9eac28e03cd23a684d81e0502797e88f3ccd27a32aeab1cfc44c39da0 + languageName: node + linkType: hard + "v8-compile-cache@npm:^2.0.3": version: 2.3.0 resolution: "v8-compile-cache@npm:2.3.0" @@ -16190,8 +16508,11 @@ __metadata: version: 0.0.0-use.local resolution: "web@workspace:packages/web" dependencies: + "@emotion/react": ^11.9.0 + "@emotion/styled": ^11.8.1 "@fontsource/roboto": ^4.2.1 - "@material-ui/core": ^4.11.3 + "@mui/material": ^5.8.2 + "@mui/styles": ^5.8.0 "@testing-library/jest-dom": ^5.11.4 "@testing-library/react": ^11.1.0 "@testing-library/user-event": ^12.1.10