diff --git a/.github/workflows/backend_tests.yml b/.github/workflows/backend_tests.yml index a0eb9935..c10f3c27 100644 --- a/.github/workflows/backend_tests.yml +++ b/.github/workflows/backend_tests.yml @@ -1,22 +1,22 @@ -name: Backend Tests - -on: - push: - paths: - - server/** - pull_request: - paths: - - server/** - -jobs: - test_backend: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3.5.3 - - - name: Start Docker - run: docker-compose -f docker-compose.test.yml up --build -d - - - name: Run Tests - run: cd server && yarn install && yarn test:actions +name: Backend Tests + +on: + push: + paths: + - server/** + pull_request: + paths: + - server/** + +jobs: + test_backend: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3.5.3 + + - name: Start Docker + run: docker-compose -f docker-compose.test.yml up --build -d + + - name: Run Tests + run: cd server && yarn install && yarn test:actions diff --git a/.github/workflows/frontend_tests.yml b/.github/workflows/frontend_tests.yml index e7b61d45..5f3b90e1 100644 --- a/.github/workflows/frontend_tests.yml +++ b/.github/workflows/frontend_tests.yml @@ -1,19 +1,19 @@ -name: Frontend Tests - -on: - push: - paths: - - client/** - pull_request: - paths: - - client/** - -jobs: - build_frontend: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3.5.3 - - - name: Build client - run: cd client && yarn install && yarn build +name: Frontend Tests + +on: + push: + paths: + - client/** + pull_request: + paths: + - client/** + +jobs: + build_frontend: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3.5.3 + + - name: Build client + run: cd client && yarn install && yarn build diff --git a/README.md b/README.md index 66789d12..917cd6ab 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![image](https://user-images.githubusercontent.com/50821962/195210327-87d8570e-d5c1-4704-be5b-eb2a609c0972.png) -# Orientation Website +# Orientation Website [![Backend Tests](https://github.com/UofT-Frosh-Orientation/orientation-website/actions/workflows/backend_tests.yml/badge.svg?event=push)](https://github.com/UofT-Frosh-Orientation/orientation-website/actions/workflows/backend_tests.yml) [![Frontend Tests](https://github.com/UofT-Frosh-Orientation/orientation-website/actions/workflows/frontend_tests.yml/badge.svg?event=push)](https://github.com/UofT-Frosh-Orientation/orientation-website/actions/workflows/frontend_tests.yml) Welcome to the University of Toronto's Frosh engineering orientation website, used by more than 1,000 incoming students each year. This website serves as the primary platform for registering and paying for orientation events, and offers a range of features including a main schedule, announcements, a personal profile page with the ability to edit, a Scunt (scavenger hunt) game, sign-up for the Frosh retreat, QR code scanning for automated registration on event day, and more. diff --git a/client/src/App.jsx b/client/src/App.jsx index 6c220cee..47bec1d2 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -8,28 +8,26 @@ import { Footer } from './components/footer/Footer'; import { useDispatch, useSelector } from 'react-redux'; import { initialsSelector, loggedInSelector, registeredSelector } from './state/user/userSlice'; import { useEffect } from 'react'; -import { getUserInfo } from './state/user/saga'; import { AskQuestionButton } from './components/button/AskQuestionButton/AskQuestionButton'; import { DarkModeProvider } from './util/DarkModeProvider'; import { SnackbarProvider } from './util/SnackbarProvider'; -import { PageMaintenance } from './pages/Maintenance/Maintenance'; -// import { getScuntSettings } from './state/scuntSettings/saga'; -// import { scuntSettingsSelector } from './state/scuntSettings/scuntSettingsSlice'; + +import { getScuntSettings } from './state/scuntSettings/saga'; +import { getUserInfo } from './state/user/saga'; export default function App() { const dispatch = useDispatch(); useEffect(() => { dispatch(getUserInfo()); - // dispatch(getScuntSettings()); + dispatch(getScuntSettings()); }, []); return ( - {/* + - */} - + ); @@ -40,7 +38,6 @@ const TransitionRoutes = () => { const loggedIn = useSelector(loggedInSelector); const registered = useSelector(registeredSelector); const initials = useSelector(initialsSelector); - // const scuntSettings = useSelector(scuntSettingsSelector); return ( @@ -48,7 +45,13 @@ const TransitionRoutes = () => { - {[...pages.main, ...pages.hidden, ...pages.special].map((page) => { + {[ + ...pages.main, + ...pages.hidden, + ...pages.special, + ...pages.scunt, + ...pages.scuntHidden, + ].map((page) => { return ( + + \ No newline at end of file diff --git a/client/src/assets/sponsors/Alumni.jpg b/client/src/assets/sponsors/Alumni.jpg new file mode 100644 index 00000000..303b5ba5 Binary files /dev/null and b/client/src/assets/sponsors/Alumni.jpg differ diff --git a/client/src/assets/sponsors/Coco.jpg b/client/src/assets/sponsors/Coco.jpg new file mode 100644 index 00000000..a16f3bd9 Binary files /dev/null and b/client/src/assets/sponsors/Coco.jpg differ diff --git a/client/src/assets/sponsors/MoguMogu.png b/client/src/assets/sponsors/MoguMogu.png new file mode 100644 index 00000000..5faa9f65 Binary files /dev/null and b/client/src/assets/sponsors/MoguMogu.png differ diff --git a/client/src/assets/sponsors/Nanis.png b/client/src/assets/sponsors/Nanis.png new file mode 100644 index 00000000..d8101518 Binary files /dev/null and b/client/src/assets/sponsors/Nanis.png differ diff --git a/client/src/assets/sponsors/Neo.jpg b/client/src/assets/sponsors/Neo.jpg new file mode 100644 index 00000000..d6ecee3f Binary files /dev/null and b/client/src/assets/sponsors/Neo.jpg differ diff --git a/client/src/assets/sponsors/OSPE.jpg b/client/src/assets/sponsors/OSPE.jpg new file mode 100644 index 00000000..f6bea532 Binary files /dev/null and b/client/src/assets/sponsors/OSPE.jpg differ diff --git a/client/src/assets/sponsors/PEO.png b/client/src/assets/sponsors/PEO.png new file mode 100644 index 00000000..b48e4360 Binary files /dev/null and b/client/src/assets/sponsors/PEO.png differ diff --git a/client/src/assets/sponsors/UTSU.jpg b/client/src/assets/sponsors/UTSU.jpg new file mode 100644 index 00000000..a065586f Binary files /dev/null and b/client/src/assets/sponsors/UTSU.jpg differ diff --git a/client/src/components/MakeSchedulePDF/MakeSchedulePDF.jsx b/client/src/components/MakeSchedulePDF/MakeSchedulePDF.jsx index 2aa1cf17..e3833e90 100644 --- a/client/src/components/MakeSchedulePDF/MakeSchedulePDF.jsx +++ b/client/src/components/MakeSchedulePDF/MakeSchedulePDF.jsx @@ -8,36 +8,37 @@ const styles = StyleSheet.create({ backgroundColor: '#E4E4E4', }, eventBubble: { - backgroundColor: '#58458f', - borderRadius: '10px', - padding: '10px', - margin: '10px' + backgroundColor: '#58458f', + borderRadius: '10px', + padding: '10px', + margin: '10px', }, eventName: { - fontSize: 12, + fontSize: 12, fontWeight: 'bold', - padding: '10px 0', - color: '#fff' + padding: '10px 0', + color: '#fff', }, eventLoc: { - fontSize: 12, - padding: '10px 0', - color: '#fff' + fontSize: 12, + padding: '10px 0', + color: '#fff', }, eventDate: { fontSize: 11, fontStyle: 'italic', color: '#fff', - padding: '5px 0' + padding: '5px 0', }, eventDesc: { - fontSize: 12, + fontSize: 12, color: '#fff', - padding: '10px 0' - } + padding: '10px 0', + }, }); const MakeSchedulePDF = (froshObject) => { + if (!froshObject) return null; const froshGroup = froshObject?.froshGroup; const scheduleData = getFroshGroupSchedule(froshGroup); @@ -53,27 +54,23 @@ const MakeSchedulePDF = (froshObject) => { {Object.keys(scheduleData).map((day) => (
- + {day} {scheduleData[day].map((scheduleDay, index) => (
- - {scheduleDay['Event Name']} - + {scheduleDay['Event Name']} {scheduleDay['Start Time']} - {scheduleDay['End Time']} - {scheduleDay['Event Location'] ? - - {scheduleDay['Event Location']} - : <> - } - {scheduleDay['Event Description'] ? - - {scheduleDay['Event Description']} - : <> - } + {scheduleDay['Event Location'] ? ( + {scheduleDay['Event Location']} + ) : null} + {scheduleDay['Event Description'] ? ( + {scheduleDay['Event Description']} + ) : null}
))}
@@ -84,4 +81,4 @@ const MakeSchedulePDF = (froshObject) => { ); }; -export { MakeSchedulePDF }; \ No newline at end of file +export { MakeSchedulePDF }; diff --git a/client/src/components/ScuntLinks/ScuntLinks.jsx b/client/src/components/ScuntLinks/ScuntLinks.jsx index 378eec62..59c3c766 100644 --- a/client/src/components/ScuntLinks/ScuntLinks.jsx +++ b/client/src/components/ScuntLinks/ScuntLinks.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useRef } from 'react'; +import React from 'react'; import { Link, useLocation } from 'react-router-dom'; import { pages } from '../../util/pages'; import { ButtonOutlined } from '../button/ButtonOutlined/ButtonOutlined'; diff --git a/client/src/components/form/RadioButtons/RadioButtons.jsx b/client/src/components/form/RadioButtons/RadioButtons.jsx index 570862d6..fe1c7e1f 100644 --- a/client/src/components/form/RadioButtons/RadioButtons.jsx +++ b/client/src/components/form/RadioButtons/RadioButtons.jsx @@ -41,7 +41,15 @@ const RadioButtons = ({ return (
{label !== undefined ?

{label}

: <>} -
+
{values.map((value, index) => { let isDisabledValue = false; if (disabledIndices !== undefined) isDisabledValue = disabledIndices?.includes(index); diff --git a/client/src/components/profile/ProfilePageResources/ProfilePageResources.jsx b/client/src/components/profile/ProfilePageResources/ProfilePageResources.jsx index 3d5130d4..823c0af3 100644 --- a/client/src/components/profile/ProfilePageResources/ProfilePageResources.jsx +++ b/client/src/components/profile/ProfilePageResources/ProfilePageResources.jsx @@ -4,7 +4,6 @@ import './ProfilePageResources.scss'; import PropTypes from 'prop-types'; export const ProfilePageResources = ({ froshObject }) => { - return (

Resources

@@ -25,13 +24,12 @@ export const ProfilePageResources = ({ froshObject }) => { ); })} - {froshObject ? ( - <> - + {froshObject ? ( + <> { - const MakeReceipt = (await import('../../MakeReceipt/MakeReceipt')).MakeReceipt; + const { MakeReceipt } = await import('../../MakeReceipt/MakeReceipt'); const ReactPDF = await import('@react-pdf/renderer'); const blob = await ReactPDF.pdf(MakeReceipt(froshObject)).toBlob(); const fileURL = URL.createObjectURL(blob); @@ -41,24 +39,21 @@ export const ProfilePageResources = ({ froshObject }) => { isSecondary style={{ margin: 0, marginTop: '10px' }} /> - - - ) : ( - <> - )} - { - const ReactPDF = await import('@react-pdf/renderer'); - const { MakeSchedulePDF } = await import('../../MakeSchedulePDF/MakeSchedulePDF'); - const blob = await ReactPDF.pdf(MakeSchedulePDF(froshObject)).toBlob(); - const fileURL = URL.createObjectURL(blob); - const pdfWindow = window.open(fileURL, '_blank'); - pdfWindow && pdfWindow.focus(); - }} - isSecondary - style={{ margin: 0, marginTop: '10px' }} - /> + { + const ReactPDF = await import('@react-pdf/renderer'); + const { MakeSchedulePDF } = await import('../../MakeSchedulePDF/MakeSchedulePDF'); + const blob = await ReactPDF.pdf(MakeSchedulePDF(froshObject)).toBlob(); + const fileURL = URL.createObjectURL(blob); + const pdfWindow = window.open(fileURL, '_blank'); + pdfWindow && pdfWindow.focus(); + }} + isSecondary + style={{ margin: 0, marginTop: '10px' }} + /> + + ) : null}
); }; diff --git a/client/src/components/profile/leedur/ProfilePageQRScanner/ProfilePageQRScanner.jsx b/client/src/components/profile/leedur/ProfilePageQRScanner/ProfilePageQRScanner.jsx index 919d2662..f10ee492 100644 --- a/client/src/components/profile/leedur/ProfilePageQRScanner/ProfilePageQRScanner.jsx +++ b/client/src/components/profile/leedur/ProfilePageQRScanner/ProfilePageQRScanner.jsx @@ -11,6 +11,7 @@ import { preKitPickUp, searchFroshList, clearFroshList, + getFood, } from '../../../../state/frosh/saga'; import PropTypes from 'prop-types'; import { capitalizeFirstLetter } from '../../../../pages/Profile/functions'; @@ -29,6 +30,8 @@ export const ProfilePageQRScanner = ({ scopes }) => { setScannerType('registration'); } else if (scopes?.includes('scanner:kits')) { setScannerType('kits'); + } else if (scopes?.includes('scanner:food')) { + setScannerType('food'); } }, [scopes]); @@ -91,6 +94,20 @@ export const ProfilePageQRScanner = ({ scopes }) => { )} ); + case 'food': + return ( + <> + {frosh['gotFood'] ? ( +
+ +
+ ) : ( +
+ +
+ )} + + ); } }; @@ -104,6 +121,8 @@ export const ProfilePageQRScanner = ({ scopes }) => { dispatch(signInFrosh({ userID })); } else if (scannerType === 'kits') { dispatch(preKitPickUp({ userID })); + } else if (scannerType === 'food') { + dispatch(getFood({ userID })); } } }} @@ -126,9 +145,16 @@ export const ProfilePageQRScanner = ({ scopes }) => { {Object.keys(frosh).map((keyPassed) => { const key = keyPassed.toString(); return ( - !['_id', 'signInDate', 'userType', 'firstName', 'preferredName', 'preKit'].includes( - key, - ) && ( + ![ + '_id', + 'signInDate', + 'userType', + 'firstName', + 'preferredName', + 'preKit', + 'isRegistered', + 'gotFood', + ].includes(key) && (
{capitalizeFirstLetter(key) + ': '} {frosh[key]?.toString()} @@ -179,6 +205,8 @@ export const ProfilePageQRScanner = ({ scopes }) => { dispatch(signInFrosh({ userID: searchResultFrosh._id })); } else if (scannerType === 'kits') { dispatch(preKitPickUp({ userID: searchResultFrosh._id })); + } else if (scannerType === 'food') { + dispatch(getFood({ userID: searchResultFrosh._id })); } }} key={searchResultFrosh.email + index} diff --git a/client/src/components/profile/scunt/ProfilePageFroshScuntTeamsSelection/ProfilePageFroshScuntTeamsSelection.jsx b/client/src/components/profile/scunt/ProfilePageFroshScuntTeamsSelection/ProfilePageFroshScuntTeamsSelection.jsx index e69b564d..6adf100e 100644 --- a/client/src/components/profile/scunt/ProfilePageFroshScuntTeamsSelection/ProfilePageFroshScuntTeamsSelection.jsx +++ b/client/src/components/profile/scunt/ProfilePageFroshScuntTeamsSelection/ProfilePageFroshScuntTeamsSelection.jsx @@ -19,14 +19,8 @@ export const ProfilePageFroshScuntTeamsSelection = () => { const { scuntSettings } = useSelector(scuntSettingsSelector); const { axios } = useAxios(); - if ( - !isRegistered || - !user?.scunt || - (scuntSettings !== undefined && - scuntSettings.length >= 1 && - scuntSettings[0]?.revealTeams === true) - ) { - return <>; + if (!isRegistered || !user?.attendingScunt || !scuntSettings || scuntSettings?.revealTeams) { + return null; } return ( diff --git a/client/src/components/profile/scunt/ProfilePageScuntToken/ProfilePageScuntToken.jsx b/client/src/components/profile/scunt/ProfilePageScuntToken/ProfilePageScuntToken.jsx index 7c920c4a..a7cfb9ba 100644 --- a/client/src/components/profile/scunt/ProfilePageScuntToken/ProfilePageScuntToken.jsx +++ b/client/src/components/profile/scunt/ProfilePageScuntToken/ProfilePageScuntToken.jsx @@ -8,71 +8,64 @@ import { ButtonOutlined } from '../../../button/ButtonOutlined/ButtonOutlined'; import './ProfilePageScuntToken.scss'; import { getScuntTeamObjFromTeamNumber } from '../../../../pages/ScuntJudgeForm/ScuntJudgeForm'; import { scuntDiscord } from '../../../../util/scunt-constants'; +import { scuntTeamsSelector } from '../../../../state/scuntTeams/scuntTeamsSlice'; -export const ProfilePageScuntToken = ({ scuntTeams, scuntTeamObjs }) => { - const { scuntSettings } = useSelector(scuntSettingsSelector); - const { user } = useSelector(userSelector); - const isRegistered = useSelector(registeredSelector); - const { setSnackbar } = useContext(SnackbarContext); - const [showToken, setShowToken] = useState(false); +// export const ProfilePageScuntToken = () => { +// const { scuntSettings } = useSelector(scuntSettingsSelector); +// const { user } = useSelector(userSelector); +// const { scuntTeams } = useSelector(scuntTeamsSelector); +// const isRegistered = useSelector(registeredSelector); +// const { setSnackbar } = useContext(SnackbarContext); +// const [showToken, setShowToken] = useState(false); +// if (!isRegistered || (scuntSettings && !scuntSettings?.revealTeams)) { +// return null; +// } - const code = user?.scuntToken; - if ( - code === undefined || - !isRegistered || - !scuntSettings || - scuntSettings.length <= 0 || - (scuntSettings !== undefined && - scuntSettings.length >= 1 && - scuntSettings[0]?.revealTeams === false) - ) { - return <>; - } - if (!user?.scunt && user?.userType !== 'leadur') { - return ( -
-

- Looking for your Scunt login Token? -

-

You have chosen not to participate in Scunt.

-
-
- ); - } - return ( -
-

{getScuntTeamObjFromTeamNumber(user?.scuntTeam, scuntTeamObjs)?.name}

- -

Team {user?.scuntTeam ? user?.scuntTeam.toString() : '‽'}

-
-

{ - setSnackbar('Copied to clipboard'); - navigator.clipboard.writeText(code); - }} - > - {code} -

-

Scunt Login Token

-

- Use this token to login to the{' '} - - Scunt Discord - -

- { - setShowToken(!showToken); - }} - /> -
- ); -}; +// if (!user?.attendingScunt && user?.userType !== 'leadur') { +// return ( +//
+//

+// Looking for your Scunt login Token? +//

+//

You have chosen not to participate in Scunt.

+//
+//
+// ); +// } +// return ( +//
+//

{getScuntTeamObjFromTeamNumber(user?.scuntTeam, scuntTeams)?.name}

+// +//

Team {user?.scuntTeam ? user?.scuntTeam.toString() : '‽'}

+//
+//

{ +// navigator.clipboard.writeText(code); +// setSnackbar('Copied to clipboard'); +// }} +// > +// {code} +//

+//

Scunt Login Token

+//

+// Use this token to login to the{' '} +// +// Scunt Discord +// +//

+// { +// setShowToken(!showToken); +// }} +// /> +//
+// ); +// }; -ProfilePageScuntToken.propTypes = { - scuntTeams: PropTypes.array, - scuntTeamObjs: PropTypes.array, -}; +// ProfilePageScuntToken.propTypes = { +// scuntTeams: PropTypes.array, +// scuntTeamObjs: PropTypes.array, +// }; diff --git a/client/src/main.jsx b/client/src/main.jsx index bf9d4b42..731ed252 100644 --- a/client/src/main.jsx +++ b/client/src/main.jsx @@ -8,8 +8,9 @@ import userSaga from './state/user/saga'; import accountsSaga from './state/accounts/saga'; import announcementsSaga from './state/announcements/saga'; import froshSaga from './state/frosh/saga'; -// import scuntSettingsSaga from './state/scuntSettings/saga'; -// import scuntMissionsSaga from './state/scuntMissions/saga'; +import scuntSettingsSaga from './state/scuntSettings/saga'; +import scuntMissionsSaga from './state/scuntMissions/saga'; +import scuntTeamsSaga from './state/scuntTeams/saga'; const store = configureAppStore(); @@ -17,8 +18,9 @@ sagaMiddleware.run(userSaga); sagaMiddleware.run(accountsSaga); sagaMiddleware.run(announcementsSaga); sagaMiddleware.run(froshSaga); -// sagaMiddleware.run(scuntSettingsSaga); -// sagaMiddleware.run(scuntMissionsSaga); +sagaMiddleware.run(scuntSettingsSaga); +sagaMiddleware.run(scuntMissionsSaga); +sagaMiddleware.run(scuntTeamsSaga); ReactDOM.createRoot(document.getElementById('root')).render( diff --git a/client/src/pages/EmailConfirmed/EmailConfirmed.jsx b/client/src/pages/EmailConfirmed/EmailConfirmed.jsx index 2b6b69c1..c91f4262 100644 --- a/client/src/pages/EmailConfirmed/EmailConfirmed.jsx +++ b/client/src/pages/EmailConfirmed/EmailConfirmed.jsx @@ -5,28 +5,19 @@ import { Link, useParams } from 'react-router-dom'; import useAxios from '../../hooks/useAxios'; const PageEmailConfirmed = () => { - const { email } = useParams(); - const { emailToken } = useParams(); - const [validEmailToken, setvalidEmailToken] = useState(false); + const { email, emailToken } = useParams(); + const [validEmailToken, setValidEmailToken] = useState(false); + const { axios } = useAxios(); - function verifyEmailToken(email, emailToken) { - const { axios } = useAxios(); - - try { - const emailAndEmailToken = { - email: email, - emailToken: emailToken, - }; - axios.post('/user/verify-user-email', emailAndEmailToken); - setvalidEmailToken(true); - } catch (err) { - setvalidEmailToken(false); + useEffect(() => { + if (emailToken && email) { + setValidEmailToken(true); } - } + }, [emailToken, email]); useEffect(() => { - verifyEmailToken(email, emailToken); - }, []); + if (validEmailToken) axios.post('/user/verify-user-email', { emailToken, email }); + }, [validEmailToken]); return (
@@ -43,7 +34,7 @@ const PageEmailConfirmed = () => { ) : (
-

Oh no! :(

+

{'Oh no! :( '}

An error occurred when trying to verify your email. Please try again later.

@@ -255,32 +228,29 @@ const ProfilePageFroshHeader = ({ editButton }) => { {'edit'} - ) : ( - <> - )} + ) : null}
- {darkMode ? ( - - ) : ( - - )} + + + {!isRegistered ? (

You are not registered!

-

You will not be able to participate in F!rosh week events until you register.

- You will not be able to participate in F!rosh week events. + {/*
- ) : ( - <> - )} + ) : null} ); }; @@ -328,8 +298,8 @@ const ProfilePageInstagrams = () => { }; const instagramLink = instagramAccounts[user?.froshGroup]; - - return isRegistered ? ( + if (!isRegistered) return null; + return (
{
- ) : ( - <> ); }; @@ -405,7 +373,7 @@ const ProfilePageAnnouncements = () => { return (

Tasks and Announcements

- {user?.canEmail === false ? ( + {!user?.canEmail ? ( { >
); @@ -432,7 +398,7 @@ const ProfilePageQRCode = () => { }, []); if (!isRegistered) { - return <>; + return null; } if (QRCodeString === undefined) { @@ -460,4 +426,38 @@ const ProfilePageQRCode = () => { ); }; +export const ProfilePageScuntTeam = () => { + const isRegistered = useSelector(registeredSelector); + const { scuntSettings } = useSelector(scuntSettingsSelector); + const { scuntTeams } = useSelector(scuntTeamsSelector); + const { user } = useSelector(userSelector); + const [scuntTeam, setScuntTeam] = useState(null); + + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getScuntSettings()); + dispatch(getScuntTeams()); + }, [dispatch]); + + useEffect(() => { + if (scuntTeams?.length) { + const [team] = scuntTeams.filter((team) => { + return team?.number === user?.scuntTeam; + }); + setScuntTeam(team); + } + }, [scuntTeams]); + + if (!isRegistered || !scuntSettings || !scuntSettings?.revealTeams) return null; + return ( +
+

Your Scunt Team:

+

+ {scuntTeam ? scuntTeam.name : null} +

+
+ ); +}; + export { PageProfileFrosh, ProfilePageFroshHeader }; diff --git a/client/src/pages/Profile/PageProfileLeader.jsx b/client/src/pages/Profile/PageProfileLeader.jsx index d71e68d6..7ed4e304 100644 --- a/client/src/pages/Profile/PageProfileLeader.jsx +++ b/client/src/pages/Profile/PageProfileLeader.jsx @@ -4,58 +4,36 @@ import WaveReverseFlip from '../../assets/misc/wave-reverse-flip.png'; import WaveReverseFlipDarkMode from '../../assets/darkmode/misc/wave-reverse-flip.png'; import { Button } from '../../components/button/Button/Button'; import { RadioButtons } from '../../components/form/RadioButtons/RadioButtons'; -import { ButtonOutlined } from '../../components/button/ButtonOutlined/ButtonOutlined'; import EditIcon from '../../assets/misc/pen-solid.svg'; import { Link } from 'react-router-dom'; -import { useSelector } from 'react-redux'; +import { useSelector, useDispatch } from 'react-redux'; import { userSelector } from '../../state/user/userSlice'; +import { scuntTeamsSelector } from '../../state/scuntTeams/scuntTeamsSlice'; import { DarkModeContext } from '../../util/DarkModeProvider'; import { SnackbarContext } from '../../util/SnackbarProvider'; // import { scuntDiscord } from '../../util/scunt-constants'; -import PropTypes from 'prop-types'; -// import { -// getScuntTeamObjFromTeamName, -// getScuntTeamObjFromTeamNumber, -// } from '../ScuntJudgeForm/ScuntJudgeForm'; -// import ScuntIcon from '../../assets/misc/magnifier.png'; -import useAxios from '../../hooks/useAxios'; +import ScuntIcon from '../../assets/misc/magnifier.png'; import { ProfilePageLeaderPermissionDashboardLinks } from '../../components/profile/leedur/PermissionDashboardLinks/ProfilePageLeaderPermissionDashboardLinks'; import { ProfilePageQRScanner } from '../../components/profile/leedur/ProfilePageQRScanner/ProfilePageQRScanner'; import { ProfilePageSchedule } from '../../components/profile/ProfilePageSchedule/ProfilePageSchedule'; import { ProfilePageResources } from '../../components/profile/ProfilePageResources/ProfilePageResources'; +import { changeScuntTeam, getScuntTeams } from '../../state/scuntTeams/saga'; +import { getScuntSettings } from '../../state/scuntSettings/saga'; // import { ProfilePageScuntToken } from '../../components/profile/scunt/ProfilePageScuntToken/ProfilePageScuntToken'; -const { axios } = useAxios(); - const PageProfileLeader = () => { const { user } = useSelector(userSelector); const qrCodeLeader = user?.authScopes?.approved.includes('scanner:registration') || - user?.authScopes?.approved.includes('scanner:kits'); - // const [scuntTeams, setScuntTeams] = useState([]); - // const [scuntTeamObjs, setScuntTeamObjs] = useState(); + user?.authScopes?.approved.includes('scanner:kits') || + user?.authScopes?.approved.includes('scanner:food'); - // const getScuntTeams = async () => { - // try { - // const response = await axios.get('/scunt-teams'); - // const { teamPoints } = response.data; - // if (teamPoints.length <= 0 || !teamPoints) setScuntTeams([]); - // else { - // setScuntTeamObjs(teamPoints); - // setScuntTeams( - // teamPoints.map((team) => { - // return team?.name; - // }), - // ); - // } - // } catch (e) { - // setScuntTeams(['Error loading teams']); - // } - // }; + const dispatch = useDispatch(); - // useEffect(() => { - // getScuntTeams(); - // }, []); + useEffect(() => { + dispatch(getScuntTeams()); + dispatch(getScuntSettings()); + }, [dispatch]); return ( <> @@ -64,130 +42,71 @@ const PageProfileLeader = () => {
- {/* */} +
{qrCodeLeader === true ? ( - <> - - - ) : ( - <> - )} - {/* */} + + ) : null} + {/* not doing discord */} - {/* */} +
); }; -// const ProfilePageScuntTeamSelectionLeader = ({ scuntTeams, scuntTeamObjs }) => { -// const { setSnackbar } = useContext(SnackbarContext); -// const [selectedScuntTeamNumber, setSelectedScuntTeamNumber] = useState(); -// const { user } = useSelector(userSelector); - -// const changeScuntTeam = async (teamNumber) => { -// const result = await axios.post('/scunt-teams/update-team', { teamNumber: teamNumber }); -// setSnackbar(result?.data?.message + ' The page will refresh in 2 seconds.'); -// setTimeout(() => { -// window.location.reload(); -// }, 2000); -// }; - -// return ( -// <> -//
-//
-//

Scunt Team

-// { -// setSelectedScuntTeamNumber(getScuntTeamObjFromTeamName(value, scuntTeamObjs)?.number); -// }} -// /> -//
-// -// ); -// }; - -// ProfilePageScuntTeamSelectionLeader.propTypes = { -// scuntTeams: PropTypes.array, -// scuntTeamObjs: PropTypes.array, -// }; +const ProfilePageScuntTeamSelectionLeader = () => { + const { setSnackbar } = useContext(SnackbarContext); + const [teamNumber, setTeamNumber] = useState(); + const { user } = useSelector(userSelector); + const { scuntTeams } = useSelector(scuntTeamsSelector); -// export const ProfilePageLeaderScuntMessage = () => { -// const { darkMode, setDarkModeStatus } = useContext(DarkModeContext); + const dispatch = useDispatch(); -// return ( -// -//
-// Scunt -//
-//

Havenger Scunt!

-//

Find more information about Scunt by clicking here!

-//
-//
-// -// ); -// }; + if (!scuntTeams?.length) return null; -// export const ProfilePageScuntToken = ({ scuntTeams, scuntTeamObjs }) => { -// const { user } = useSelector(userSelector); -// const { setSnackbar } = useContext(SnackbarContext); -// const [showToken, setShowToken] = useState(false); -// const code = user?.scuntToken; + return ( +
+
+

Scunt Team

+ + team.name)} + onSelected={(value) => { + const [team] = scuntTeams.filter((team) => team.name === value); + setTeamNumber(team?.number); + }} + /> +
+ ); +}; -// return ( -//
-//

{getScuntTeamObjFromTeamNumber(user?.scuntTeam, scuntTeamObjs)?.name}

-// -//

Team {user?.scuntTeam ? user?.scuntTeam.toString() : '‽'}

-//
-//

{ -// setSnackbar('Copied to clipboard'); -// navigator.clipboard.writeText(code); -// }} -// > -// {code} -//

-//

Scunt Login Token

-//

-// Use this token to login to the{' '} -// -// Scunt Discord -// -//

-// { -// setShowToken(!showToken); -// }} -// /> -//
-// ); -// }; +export const ProfilePageLeaderScuntMessage = () => { + const { darkMode, setDarkModeStatus } = useContext(DarkModeContext); -// ProfilePageScuntToken.propTypes = { -// scuntTeams: PropTypes.array, -// scuntTeamObjs: PropTypes.array, -// }; + return ( + +
+ Scunt +
+

Havenger Scunt!

+

Find more information about Scunt by clicking here!

+
+
+ + ); +}; const ProfilePageLeaderHeader = () => { const { user } = useSelector(userSelector); @@ -217,7 +136,6 @@ const ProfilePageLeaderHeader = () => { {user?.preferredName} )}

- {user?.discipline &&

{`Incoming ${user['discipline']} Engineering student`}

}

{user?.email}

@@ -230,19 +148,16 @@ const ProfilePageLeaderHeader = () => {
- {darkMode ? ( - - ) : ( - - )} + {leaderApproved === false ? (

Your Leedur Account is not Approved!

Please contact a VC to get your account approved.

- ) : ( - <> - )} + ) : null} ); }; diff --git a/client/src/pages/Profile/Profile.scss b/client/src/pages/Profile/Profile.scss index 07995859..15dc6bc8 100644 --- a/client/src/pages/Profile/Profile.scss +++ b/client/src/pages/Profile/Profile.scss @@ -378,3 +378,11 @@ margin-left: 0; } } + +.profile-page-scunt-team { + margin-top: 20px; + text-align: center; + h2 { + margin-top: 10px; + } +} diff --git a/client/src/pages/ScopeRequest/functions.jsx b/client/src/pages/ScopeRequest/functions.jsx index 02511246..c85859ee 100644 --- a/client/src/pages/ScopeRequest/functions.jsx +++ b/client/src/pages/ScopeRequest/functions.jsx @@ -39,7 +39,7 @@ export const getTotalScopes = () => { accounts: ['read', 'edit', 'delete'], email: ['send'], timeline: ['create', 'edit', 'delete'], - scanner: ['registration', 'kits'], + scanner: ['registration', 'kits', 'food'], scunt: [ 'judge missions', 'judge bribe points', diff --git a/client/src/pages/ScuntGameSettings/ScuntGameSettings.jsx b/client/src/pages/ScuntGameSettings/ScuntGameSettings.jsx index 6b3d4dc4..78342e81 100644 --- a/client/src/pages/ScuntGameSettings/ScuntGameSettings.jsx +++ b/client/src/pages/ScuntGameSettings/ScuntGameSettings.jsx @@ -1,6 +1,5 @@ -import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { Link, useNavigate } from 'react-router-dom'; import './ScuntGameSettings.scss'; @@ -10,21 +9,25 @@ import { Checkboxes } from '../../components/form/Checkboxes/Checkboxes'; import { useDispatch, useSelector } from 'react-redux'; import { + getJudges, + giveJudgeBribePoints, getScuntSettings, setScuntSettings, - shuffleScuntTeams, } from '../../state/scuntSettings/saga'; -import { scuntSettingsSelector } from '../../state/scuntSettings/scuntSettingsSlice'; +import { shuffleScuntTeams, setScuntTeams, getScuntTeams } from '../../state/scuntTeams/saga'; +import { + scuntJudgeSelector, + scuntSettingsSelector, +} from '../../state/scuntSettings/scuntSettingsSlice'; import { SnackbarContext } from '../../util/SnackbarProvider'; import { convertCamelToLabel } from '../ScopeRequest/ScopeRequest'; import { Dropdown } from '../../components/form/Dropdown/Dropdown'; -import useAxios from '../../hooks/useAxios'; import { PopupModal } from '../../components/popup/PopupModal'; -const { axios } = useAxios(); +import { scuntTeamsSelector } from '../../state/scuntTeams/scuntTeamsSlice'; -const scuntsettings = [ +const scuntSettingsInfo = [ { parameter: 'Amount of Teams', key: 'amountOfTeams', // key in the model @@ -50,12 +53,6 @@ const scuntsettings = [ 'The min amount of points allowed to be given out over the recommended amount for missions', placeholder: 0.3, }, - { - parameter: 'Discord Link', - key: 'discordLink', - description: 'if blank the discord link will be set to the one in the database', - placeholder: 'https://discord.com/', - }, ]; const scuntsettingbool = [ @@ -63,14 +60,10 @@ const scuntsettingbool = [ parameter: 'Reveal Judges and Bribes', key: 'revealJudgesAndBribes', }, - { - parameter: 'Reveal Teams', - key: 'revealTeams', - }, - { - parameter: 'Show Discord Link', - key: 'showDiscordLink', - }, + // { + // parameter: 'Show Discord Link', + // key: 'showDiscordLink', + // }, { parameter: 'Reveal Leaderboard', key: 'revealLeaderboard', @@ -79,6 +72,10 @@ const scuntsettingbool = [ parameter: 'Reveal Missions', key: 'revealMissions', }, + { + parameter: 'Reveal Teams', + key: 'revealTeams', + }, { parameter: 'Allow Judging', key: 'allowJudging', @@ -93,13 +90,17 @@ const ScuntGameSettings = () => { const { setSnackbar } = useContext(SnackbarContext); useEffect(() => { - if (scuntSettings !== undefined) { - setNewSettings(scuntSettings[0]); - } + if (scuntSettings) setNewSettings(scuntSettings); }, [scuntSettings]); + useEffect(() => { + dispatch(getScuntSettings(setSnackbar)); + dispatch(getScuntTeams(setSnackbar)); + dispatch(getJudges(setSnackbar)); + }, [dispatch]); + const initialSettings = { - name: 'Scunt2T3 Settings', + name: 'Scunt 2T3 Settings', amountOfTeams: 10, amountOfStarterBribePoints: 2500, maxAmountPointsPercent: 0.3, @@ -118,17 +119,16 @@ const ScuntGameSettings = () => {
- {scuntsettings.map((i) => { + {scuntSettingsInfo.map((setting) => { return ( -
+
{ ); })}
- - -
-
- - - -
-
- - {/* */} - - {/*
-
*/} - - {/* */} - - {/*
-
*/} - - - -
-
-
- {scuntsettingbool.map((i) => { - let selectedCheck = []; - - if (newSettings && newSettings[i.key] === true) { - selectedCheck = [0]; - } - - return ( -
- { - let tempSettings = { ...newSettings }; // create a copy - tempSettings[i.key] = state; - setNewSettings(tempSettings); - }} - /> -
- ); - })} + {newSettings ? ( + setting.parameter)} + initialSelectedIndices={scuntsettingbool.reduce((prev, setting, index) => { + if (newSettings?.[setting.key]) prev.push(index); + return prev; + }, [])} + onSelected={(value, index, state) => { + setNewSettings({ + ...newSettings, + [scuntsettingbool[index].key]: state, + }); + }} + /> + ) : null}
{ }} />
+ +
+
+ + + +
+
+ + + +
+
); @@ -323,31 +305,16 @@ const RefillJudgeBribePoints = () => { const [assignedBribeRefillPoints, setAssignedBribeRefillPoints] = useState(0); const [assignedJudge, setAssignedJudge] = useState(''); const [clearPointsInput, setClearPointsInput] = useState(false); - const [judges, setJudges] = useState([]); - - const getJudgeUsers = async () => { - try { - const response = await axios.get('/scunt-teams/judges'); - const { users } = response.data; - if (users.length <= 0 || !users) setJudges([]); - else setJudges(users); - } catch (e) { - setJudges([]); - } - }; - const judgeUsersGetter = async () => { - getJudgeUsers(); - }; + // const [judges, setJudges] = useState([]); + const { judges } = useSelector(scuntJudgeSelector); - useEffect(() => { - judgeUsersGetter(); - }, []); + const dispatch = useDispatch(); return (

Judge Status

- {judges.map((judge) => { + {judges?.map((judge) => { return (

{judge?.firstName + ' ' + judge?.lastName} @@ -384,6 +351,7 @@ const RefillJudgeBribePoints = () => {

{ setAssignedBribeRefillPoints(value); }} @@ -399,13 +367,21 @@ const RefillJudgeBribePoints = () => { setSnackbar('Please set a points value', true); } else { //Refill judges bribe points here - const response = await axios.post('/scunt-teams/transaction/refill-bribe', { - judgeUserId: assignedJudge?._id, - points: assignedBribeRefillPoints, - isAddPoints: true, - }); - setSnackbar(response?.data?.message + ' to ' + assignedJudge?.firstName); - getJudgeUsers(); + // const response = await axios.post('/scunt-teams/transaction/refill-bribe', { + // judgeUserId: assignedJudge?._id, + // points: assignedBribeRefillPoints, + // isAddPoints: true, + // }); + // setSnackbar(response?.data?.message + ' to ' + assignedJudge?.firstName); + // getJudgeUsers(); + dispatch( + giveJudgeBribePoints({ + setSnackbar, + judgeUserId: assignedJudge?._id, + points: assignedBribeRefillPoints, + isAddPoints: true, + }), + ); setAssignedBribeRefillPoints(0); setClearPointsInput(true); } @@ -416,37 +392,18 @@ const RefillJudgeBribePoints = () => { }; const RenameTeams = () => { + const dispatch = useDispatch(); const { setSnackbar } = useContext(SnackbarContext); - + const { scuntTeams } = useSelector(scuntTeamsSelector); const [teamObjs, setTeamObjs] = useState([]); - const getScuntTeams = async () => { - try { - const response = await axios.get('/scunt-teams'); - const { teamPoints } = response.data; - if (teamPoints.length <= 0 || !teamPoints) setTeamObjs([]); - else { - setTeamObjs(teamPoints); - } - } catch (e) { - setTeamObjs(['Error loading teams']); - } - }; - - const renameScuntTeams = async () => { - try { - const result = await axios.put('/scunt-teams/rename-teams', { - teamObjs: teamObjs, - }); - setSnackbar(result?.data?.message); - } catch (e) { - setSnackbar(e.toString(), true); - } - }; + useEffect(() => { + if (scuntTeams?.length) setTeamObjs(scuntTeams); + }, [scuntTeams]); useEffect(() => { - getScuntTeams(); - }, []); + dispatch(getScuntTeams(setSnackbar)); + }, [dispatch]); return (
@@ -454,23 +411,27 @@ const RenameTeams = () => {
{teamObjs.map((teamObj, index) => { return ( - <> - { - teamObjs[index]['name'] = value; - }} - initialValue={teamObj?.name} - label={'Team ' + teamObj?.number} - /> - + { + setTeamObjs( + teamObjs.map((team, i) => (i === index ? { ...team, name: value } : team)), + ); + }} + initialValue={teamObj?.name} + label={'Team ' + teamObj?.number} + /> ); })}
@@ -594,15 +555,7 @@ const HideRevealMissions = () => { }; const CurrentScuntGameSettings = () => { - const { scuntSettings } = useSelector(scuntSettingsSelector); // returns an array of scunt settings - const [keys, setKeys] = useState([]); - - useEffect(() => { - // this is to catch the initially undefined settings - if (scuntSettings && scuntSettings[0]) { - setKeys(Object.keys(scuntSettings[0])); - } - }, [scuntSettings]); + const { scuntSettings } = useSelector(scuntSettingsSelector); return (
@@ -610,28 +563,30 @@ const CurrentScuntGameSettings = () => { Current Scunt Settings - {scuntSettings !== undefined ? ( - keys?.map((i) => { - if (i !== 'name' && i !== 'id') { + {scuntSettings ? ( + Object.keys(scuntSettings)?.map((settingKey) => { + if (!['_id', 'name', '__v'].includes(settingKey)) { // no need to show the parameters above return ( -

- {convertCamelToLabel(i)} +

+ {convertCamelToLabel(settingKey)} {': '} - {scuntSettings[0][i] === true || scuntSettings[0][i] === false ? ( -

- {scuntSettings[0][i].toString()} -
- ) : scuntSettings[0][i] == null ? ( + {scuntSettings[settingKey].toString()} + + ) : scuntSettings[settingKey] == null ? ( '' ) : ( - scuntSettings[0][i].toString() + scuntSettings[settingKey].toString() )}

); @@ -651,7 +606,6 @@ const ScuntGameSettingsTextbox = ({ parameter, description, placeholder, - initialValue, newSettings, setNewSettings, }) => { @@ -675,11 +629,10 @@ const ScuntGameSettingsTextbox = ({ inputType={'text'} label={parameter} description={description} - // initialValue={initialValue} onChange={(input) => handleInput(input, objKey)} placeholder={String(placeholder)} onEnterKey={(input) => handleInput(input, objKey)} - > + />
); diff --git a/client/src/pages/ScuntHome/ScuntHome.jsx b/client/src/pages/ScuntHome/ScuntHome.jsx index f5cddc6f..c4b48cf3 100644 --- a/client/src/pages/ScuntHome/ScuntHome.jsx +++ b/client/src/pages/ScuntHome/ScuntHome.jsx @@ -5,143 +5,62 @@ import WaveDarkMode from '../../assets/darkmode/misc/wave.png'; import waveBottom from '../../assets/misc/wave-reverse.png'; import waveBottomDarkMode from '../../assets/darkmode/misc/wave-reverse.png'; import { Confetti } from '../../components/misc/Confetti/Confetti'; -import { Link, useLocation } from 'react-router-dom'; +import { Link } from 'react-router-dom'; import { ScuntLinks } from '../../components/ScuntLinks/ScuntLinks'; import { DarkModeContext } from '../../util/DarkModeProvider'; -// import { ProfilePageScuntToken } from '../Profile/PageProfileFrosh'; -import DiscordIcon from '../../assets/social/discord-brands.svg'; +// import DiscordIcon from '../../assets/social/discord-brands.svg'; import { aboutScunt, okayToInviteToScunt, scuntDiscord } from '../../util/scunt-constants'; import { useDispatch, useSelector } from 'react-redux'; import { userSelector } from '../../state/user/userSlice'; import { scuntSettingsSelector } from '../../state/scuntSettings/scuntSettingsSlice'; import useAxios from '../../hooks/useAxios'; -import { ProfilePageScuntToken } from '../../components/profile/scunt/ProfilePageScuntToken/ProfilePageScuntToken'; +// import { ProfilePageScuntToken } from '../../components/profile/scunt/ProfilePageScuntToken/ProfilePageScuntToken'; +import { scuntTeamsSelector } from '../../state/scuntTeams/scuntTeamsSlice'; +import { getScuntSettings } from '../../state/scuntSettings/saga'; +import { getScuntTeams } from '../../state/scuntTeams/saga'; +// import { ProfilePageScuntTeam } from '../Profile/PageProfileFrosh'; const { axios } = useAxios(); export const PageScuntHome = () => { + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getScuntSettings()); + dispatch(getScuntTeams()); + }, [dispatch]); + return ( <> -
- ); }; -const ScuntDiscord = () => { - const { scuntSettings, loading } = useSelector(scuntSettingsSelector); - const [showDiscordLink, setShowDiscordLink] = useState(false); - const [discordLink, setDiscordLink] = useState(''); - const [revealTeams, setRevealTeams] = useState(false); - - const { user } = useSelector(userSelector); - const leader = user?.userType === 'leadur'; - - const dispatch = useDispatch(); - - useEffect(() => { - if (scuntSettings !== undefined) { - let settings = scuntSettings[0]; - - setRevealTeams(settings?.revealTeams); - setShowDiscordLink(settings?.showDiscordLink); - setDiscordLink(settings?.discordLink); - } - }, [scuntSettings]); - - if (showDiscordLink !== true && revealTeams !== true && !leader) { - // catch the undef states of the selector using !== true - return
; - } else { - const { darkMode, setDarkModeStatus } = useContext(DarkModeContext); - return ( - - ); - } -}; - const AboutScunt = () => { - const { darkMode, setDarkModeStatus } = useContext(DarkModeContext); - const [scuntTeams, setScuntTeams] = useState([]); - const [scuntTeamObjs, setScuntTeamObjs] = useState(); - - const getScuntTeams = async () => { - try { - const response = await axios.get('/scunt-teams'); - const { teamPoints } = response.data; - if (teamPoints.length <= 0 || !teamPoints) setScuntTeams([]); - else { - setScuntTeamObjs(teamPoints); - setScuntTeams( - teamPoints.map((team) => { - return team?.name; - }), - ); - } - } catch (e) { - console.error(e.toString()); - setScuntTeams(['Error loading teams']); - } - }; - - useEffect(() => { - getScuntTeams(); - }, []); + const { darkMode } = useContext(DarkModeContext); return ( <> - {darkMode ? ( - - ) : ( - - )} +
-
- -
+ {/*
+ +
*/}

Check the Rules for more information

- {darkMode ? ( - wave - ) : ( - wave - )} + wave +
); @@ -151,11 +70,11 @@ const ScuntCountdown = () => { const { scuntSettings, loading } = useSelector(scuntSettingsSelector); const [targetDate, setTargetDate] = useState(); const [countDownDate, setCountDownDate] = useState(); - //const [targetDate, targetDate] + const [countDown, setCountDown] = useState(countDownDate - new Date().getTime()); useEffect(() => { if (scuntSettings !== undefined) { - let settings = scuntSettings[0]; + let settings = scuntSettings; const tempDate = new Date(settings?.scuntDate); const tempCountDownDate = new Date(tempDate).getTime(); @@ -164,11 +83,6 @@ const ScuntCountdown = () => { } }, [scuntSettings]); - //const targetDate = new Date(scuntDate); - //const countDownDate = new Date(targetDate).getTime(); - - const [countDown, setCountDown] = useState(countDownDate - new Date().getTime()); - useEffect(() => { const interval = setInterval(() => { setCountDown(countDownDate - new Date().getTime()); @@ -222,3 +136,62 @@ const ScuntCountdown = () => {
); }; + +// const ScuntDiscord = () => { +// const { scuntSettings, loading } = useSelector(scuntSettingsSelector); +// const [showDiscordLink, setShowDiscordLink] = useState(false); +// const [discordLink, setDiscordLink] = useState(''); +// const [revealTeams, setRevealTeams] = useState(false); + +// const { user } = useSelector(userSelector); +// const leader = user?.userType === 'leadur'; + +// useEffect(() => { +// if (scuntSettings !== undefined) { +// let settings = scuntSettings[0]; + +// setRevealTeams(settings?.revealTeams); +// setShowDiscordLink(settings?.showDiscordLink); +// setDiscordLink(settings?.discordLink); +// } +// }, [scuntSettings]); + +// if (showDiscordLink !== true && revealTeams !== true && !leader) { +// // catch the undef states of the selector using !== true +// return null; +// } else { +// const { darkMode, setDarkModeStatus } = useContext(DarkModeContext); +// return ( +// +// ); +// } +// }; diff --git a/client/src/pages/ScuntJudgeForm/ScuntJudgeForm.jsx b/client/src/pages/ScuntJudgeForm/ScuntJudgeForm.jsx index 118f03d0..6a145203 100644 --- a/client/src/pages/ScuntJudgeForm/ScuntJudgeForm.jsx +++ b/client/src/pages/ScuntJudgeForm/ScuntJudgeForm.jsx @@ -4,7 +4,6 @@ import './ScuntJudgeForm.scss'; import { TextInput } from '../../components/input/TextInput/TextInput'; import { useDispatch, useSelector } from 'react-redux'; import { userSelector } from '../../state/user/userSlice'; -import { list } from './scuntTempData'; import ReactSlider from 'react-slider'; import { Dropdown } from '../../components/form/Dropdown/Dropdown'; import { Button } from '../../components/button/Button/Button'; @@ -13,11 +12,16 @@ import { SnackbarContext } from '../../util/SnackbarProvider'; import { scuntSettingsSelector } from '../../state/scuntSettings/scuntSettingsSlice'; import { getScuntSettings } from '../../state/scuntSettings/saga'; import { submitBribePoints } from './functions'; -import star from '../../assets/misc/star-solid.svg'; +import greenCheck from '../../assets/misc/check-solid-green.svg'; import { scuntMissionsSelector } from '../../state/scuntMissions/scuntMissionsSlice'; import { getScuntMissions } from '../../state/scuntMissions/saga'; -import useAxios from '../../hooks/useAxios'; -const { axios } = useAxios(); +import { missionStatusSelector, scuntTeamsSelector } from '../../state/scuntTeams/scuntTeamsSlice'; +import { + addPoints, + getMissionStatus, + getScuntTeams, + subtractPoints, +} from '../../state/scuntTeams/saga'; export const getScuntTeamObjFromTeamName = (teamName, teamObjs) => { if (!teamName || !teamObjs) { @@ -41,53 +45,52 @@ export const PageScuntJudgeForm = () => { const { user } = useSelector(userSelector); const dispatch = useDispatch(); const { missions } = useSelector(scuntMissionsSelector); + const { scuntTeams } = useSelector(scuntTeamsSelector); + const { scuntSettings } = useSelector(scuntSettingsSelector); const { setSnackbar } = useContext(SnackbarContext); const [teams, setTeams] = useState(['Select Team']); const [teamObjs, setTeamObjs] = useState(); - const getScuntTeams = async () => { - try { - const response = await axios.get('/scunt-teams'); - const { teamPoints } = response.data; - if (teamPoints.length <= 0 || !teamPoints) setTeams([]); - else { - setTeamObjs(teamPoints); - setTeams( - teamPoints.map((team) => { - return team?.name; - }), - ); - } - } catch (e) { - setTeams(['Error loading teams']); - } - }; - useEffect(() => { - dispatch(getScuntMissions({ showHidden: false })); - getScuntTeams(); + dispatch(getScuntMissions({ showHidden: false, setSnackbar })); + dispatch(getScuntSettings(setSnackbar)); + dispatch(getScuntTeams(setSnackbar)); }, []); - return ( - <> + useEffect(() => { + if (scuntTeams?.length) { + setTeamObjs(scuntTeams); + setTeams(['Select Team', ...scuntTeams.map((team) => team?.name)]); + } + }, [scuntTeams]); + + if (!scuntSettings?.allowJudging) + return (
-

Judge Dashboard

-

- Hello,{' '} - {user?.preferredName === '' || !user?.preferredName - ? user?.firstName - : user?.preferredName} -

- -
- -
- +

Judging is not currently allowed.

- + ); + + return ( +
+
+

Judge Dashboard

+

+ Hello,{' '} + {user?.preferredName === '' || !user?.preferredName + ? user?.firstName + : user?.preferredName} +

+ +
+ +
+ +
+
); }; @@ -99,6 +102,8 @@ const ScuntNegativePoints = ({ teams, teamObjs }) => { const { setSnackbar } = useContext(SnackbarContext); + const dispatch = useDispatch(); + return (
@@ -126,7 +131,7 @@ const ScuntNegativePoints = ({ teams, teamObjs }) => {
{ if (isNaN(parseInt(value))) { return; @@ -182,11 +187,15 @@ const ScuntNegativePoints = ({ teams, teamObjs }) => { } setAssignedPoints(0); //Subtract points here - const response = await axios.post('/scunt-teams/transaction/subtract', { - teamNumber: assignedTeam?.number, - points: assignedPoints, - }); - setSnackbar(response?.data?.message); + + dispatch( + subtractPoints({ + teamNumber: assignedTeam?.number, + points: assignedPoints, + setSnackbar, + }), + ); + setClearPointsInput(true); }} /> @@ -258,7 +267,7 @@ const ScuntBribePoints = ({ teams, teamObjs }) => {
{ if (isNaN(parseInt(value))) { return; @@ -332,48 +341,48 @@ ScuntBribePoints.propTypes = { teamObjs: PropTypes.array, }; -const ScuntMissionSelection = ({ missions, teams: teamsPassed, teamObjs }) => { - const teams = ['Select Team', ...teamsPassed]; - const { scuntSettings, loading } = useSelector(scuntSettingsSelector); +const ScuntMissionSelection = ({ missions, teams, teamObjs }) => { + const { scuntSettings } = useSelector(scuntSettingsSelector); + const { missionStatus } = useSelector(missionStatusSelector); + const { setSnackbar } = useContext(SnackbarContext); const [maxAmountPointsPercent, setMaxAmountPointsPercent] = useState(0); const [minAmountPointsPercent, setMinAmountPointsPercent] = useState(0); + const [assignedMission, setAssignedMission] = useState(undefined); + const [searchedMissions, setSearchedMissions] = useState([]); + const [assignedPoints, setAssignedPoints] = useState(0); + const [assignedTeam, setAssignedTeam] = useState(''); + const [clearText, setClearText] = useState(false); + const [clearPointsInput, setClearPointsInput] = useState(false); + const [hasQRScanned, setHasQRScanned] = useState(false); const dispatch = useDispatch(); useEffect(() => { - dispatch(getScuntSettings()); - }, []); + dispatch(getScuntSettings(setSnackbar)); + }, [dispatch]); useEffect(() => { - if (scuntSettings !== undefined) { - if (Array.isArray(scuntSettings)) { - setMinAmountPointsPercent(scuntSettings[0]?.minAmountPointsPercent); - setMaxAmountPointsPercent(scuntSettings[0]?.maxAmountPointsPercent); - } + if (scuntSettings) { + setMinAmountPointsPercent(scuntSettings.minAmountPointsPercent); + setMaxAmountPointsPercent(scuntSettings.maxAmountPointsPercent); } }, [scuntSettings]); - const [assignedMission, setAssignedMission] = useState(undefined); - const [missionStatus, setMissionStatus] = useState(undefined); - const [searchedMissions, setSearchedMissions] = useState([]); - const [assignedPoints, setAssignedPoints] = useState(0); - const [assignedTeam, setAssignedTeam] = useState(''); - const [clearText, setClearText] = useState(false); - const [clearPointsInput, setClearPointsInput] = useState(false); - const [hasQRScanned, setHasQRScanned] = useState(false); - const { setSnackbar } = useContext(SnackbarContext); + useEffect(() => { + if (assignedMission && assignedTeam) + dispatch( + getMissionStatus({ + missionNumber: assignedMission?.number, + teamNumber: assignedTeam?.number, + }), + ); + }, [dispatch, assignedMission, assignedTeam]); - const getMissionStatus = async (mission, team) => { - if (!team || !mission) return 0; - const response = await axios.post('/scunt-teams/transaction/check', { - teamNumber: team?.number, - missionNumber: mission?.number, - }); - setMissionStatus(response?.data?.missionStatus); - if (response?.data?.missionStatus?.points) { - setAssignedPoints(response?.data?.missionStatus?.points); + useEffect(() => { + if (missionStatus) { + setAssignedPoints(missionStatus?.points || assignedMission?.points); } - }; + }, [missionStatus]); const getMissionSearchName = (searchName) => { if (searchName === '') { @@ -401,10 +410,6 @@ const ScuntMissionSelection = ({ missions, teams: teamsPassed, teamObjs }) => { getMissionSearchName(''); }; - useEffect(() => { - getMissionStatus(assignedMission, assignedTeam); - }, [assignedMission, assignedTeam]); - return ( <> { />
{assignedMission !== undefined ? ( -
{ - setAssignedMission(undefined); - setSearchedMissions([]); - setClearText(true); - }} - > - +
+
) : ( searchedMissions.map((mission) => { @@ -490,7 +493,11 @@ const ScuntMissionSelection = ({ missions, teams: teamsPassed, teamObjs }) => { setAssignedPoints(mission?.points); }} > - +
); }) @@ -528,7 +535,7 @@ const ScuntMissionSelection = ({ missions, teams: teamsPassed, teamObjs }) => {
{ if (isNaN(parseInt(value))) { return; @@ -565,9 +572,7 @@ const ScuntMissionSelection = ({ missions, teams: teamsPassed, teamObjs }) => {

- ) : ( - <> - )} + ) : null}
{ setSnackbar('Please select a team!', true); return; } - const response = await axios.post('/scunt-teams/transaction/add', { - teamNumber: assignedTeam?.number, - missionNumber: assignedMission?.number, - points: assignedPoints, - }); - setSnackbar(response?.data?.message); + dispatch( + addPoints({ + teamNumber: assignedTeam?.number, + missionNumber: assignedMission?.number, + points: assignedPoints, + setSnackbar, + }), + ); setAssignedPoints(0); setClearText(true); setAssignedMission(undefined); @@ -624,9 +631,7 @@ const ScuntMissionSelection = ({ missions, teams: teamsPassed, teamObjs }) => { Mission {assignedMission?.number} - {assignedPoints} Points
- ) : ( - <> - )} + ) : null} ); }; @@ -637,27 +642,38 @@ ScuntMissionSelection.propTypes = { teamObjs: PropTypes.array, }; -export const ScuntMissionEntry = ({ mission, selected }) => { +export const ScuntMissionEntry = ({ mission, selected, completed, pointsAwarded }) => { return (

{mission?.number}

- {mission?.isJudgingStation ? ( + {completed ? ( judging station indication - ) : ( - <> - )} + ) : null}

{mission?.name}

-

{mission?.points}

+ {completed ? ( +

+ {pointsAwarded}/{mission?.points} +

+ ) : ( +

{mission?.points}

+ )}
); }; ScuntMissionEntry.propTypes = { + completed: PropTypes.bool, + pointsAwarded: PropTypes.number, mission: PropTypes.object, selected: PropTypes.bool, }; + +ScuntMissionEntry.defaultProps = { + completed: false, + pointsAwarded: 0, +}; diff --git a/client/src/pages/ScuntJudges/ScuntJudges.jsx b/client/src/pages/ScuntJudges/ScuntJudges.jsx index 466da7a0..6b1f8939 100644 --- a/client/src/pages/ScuntJudges/ScuntJudges.jsx +++ b/client/src/pages/ScuntJudges/ScuntJudges.jsx @@ -20,9 +20,15 @@ const ScuntJudges = () => { const { scuntSettings, loading } = useSelector(scuntSettingsSelector); // returns array const [revealJudgesAndBribes, setRevealJudgesAndBribes] = useState(false); + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getScuntSettings()); + }, [dispatch]); + useEffect(() => { if (scuntSettings !== undefined) { - setRevealJudgesAndBribes(scuntSettings[0]?.revealJudgesAndBribes); + setRevealJudgesAndBribes(scuntSettings?.revealJudgesAndBribes); } }, [scuntSettings]); diff --git a/client/src/pages/ScuntLeaderboard/ScuntLeaderboard.jsx b/client/src/pages/ScuntLeaderboard/ScuntLeaderboard.jsx index eb972472..7911bca6 100644 --- a/client/src/pages/ScuntLeaderboard/ScuntLeaderboard.jsx +++ b/client/src/pages/ScuntLeaderboard/ScuntLeaderboard.jsx @@ -11,10 +11,9 @@ import secondPlace from '../../assets/scuntleaderboard/second-medal.svg'; import thirdPlace from '../../assets/scuntleaderboard/third-medal.svg'; import { Button } from '../../components/button/Button/Button'; -import { useDispatch, useSelector } from 'react-redux'; -import { registeredSelector, userSelector } from '../../state/user/userSlice'; +import { useSelector } from 'react-redux'; +import { loggedInSelector, userSelector } from '../../state/user/userSlice'; import { scuntSettingsSelector } from '../../state/scuntSettings/scuntSettingsSlice'; -import { getScuntSettings } from '../../state/scuntSettings/saga'; import io from 'socket.io-client'; const test = [ @@ -55,7 +54,8 @@ const buttonStyle = { width: 'fit-content' }; const ScuntLeaderboard = () => { const { user } = useSelector(userSelector); const leader = user?.userType === 'leadur'; - const { scuntSettings, loading } = useSelector(scuntSettingsSelector); + const loggedIn = useSelector(loggedInSelector); + const { scuntSettings } = useSelector(scuntSettingsSelector); const [revealJudgesAndBribes, setRevealJudgesAndBribes] = useState(false); const socket = io(`${import.meta.env.VITE_API_BASE_URL}/leaderboard`, { autoConnect: false }); const [leaderboard, setLeaderboard] = useState([]); @@ -93,15 +93,13 @@ const ScuntLeaderboard = () => { }; }, []); - const dispatch = useDispatch(); - useEffect(() => { - if (scuntSettings !== undefined) { - setRevealJudgesAndBribes(scuntSettings[0]?.revealJudgesAndBribes); + if (scuntSettings) { + setRevealJudgesAndBribes(scuntSettings?.revealJudgesAndBribes); } }, [scuntSettings]); - if (revealJudgesAndBribes !== true && !leader) { + if ((revealJudgesAndBribes !== true && !leader) || !loggedIn || !user?.attendingScunt) { return (
@@ -154,7 +152,6 @@ const ScuntLeaderboardShow = ({ leaderboard }) => { return team; }); - console.table(result); return result; }, [leaderboard]); const handle = useFullScreenHandle(); @@ -207,26 +204,23 @@ const ScuntLeaderboardFullScreen = ({ arr }) => { }; const ScuntLeaderboardDesktop = ({ arr }) => { - console.table(arr); return ( - <> -
- - {arr?.map((item) => { - let key = item.name + String(item.number); - return ( - - ); - })} -
-
- +
+ + {arr?.map((item) => { + let key = item.name + String(item.number); + return ( + + ); + })} +
+
); }; @@ -234,61 +228,59 @@ const ScuntLeaderboardMobile = ({ arr }) => { arr.sort((a, b) => b.computedPoints - a.computedPoints); return ( - <> -
- {arr.map((item) => { - let rank = arr.indexOf(item) + 1; - let key = item.name + String(item.number); - if (rank === 1) { - // first place - return ( - - ); - } else if (rank === 2) { - // second place - return ( - - ); - } else if (rank === 3) { - return ( - - ); - } else { - return ( - - ); - } - })} -
- +
+ {arr.map((item) => { + let rank = arr.indexOf(item) + 1; + let key = item.name + String(item.number); + if (rank === 1) { + // first place + return ( + + ); + } else if (rank === 2) { + // second place + return ( + + ); + } else if (rank === 3) { + return ( + + ); + } else { + return ( + + ); + } + })} +
); }; @@ -323,64 +315,60 @@ const ScuntLeaderboardBar = ({ name, number, points, barwidth }) => { const ScuntLeaderboardBarVertical = ({ name, number, points, barwidth }) => { return ( - <> -
-
-
-

- {points}pts -

-
-
-

{name}

-

Group {number}

-
+
+
+
+

+ {points}pts +

- +
+

{name}

+

Group {number}

+
+
); }; // for mobile const ScuntLeaderboardBubble = ({ name, number, points, rank, img, barwidth }) => { return ( - <> -
-
- {img !== undefined ? ( - - ) : ( - <> - )} -
-
- {rank !== undefined ? ( -

{rank}

- ) : ( -

- )} -
-

{name}

-

Group {number}

-
+
+
+ {img !== undefined ? ( + + ) : ( + <> + )} +
+
+ {rank !== undefined ? ( +

{rank}

+ ) : ( +

+ )} +
+

{name}

+

Group {number}

- {/*
*/} -

{points + ' pts'}

- {/*
*/}
+ {/*
*/} +

{points + ' pts'}

+ {/*
*/}
- +
); }; diff --git a/client/src/pages/ScuntMissionsDashboard/ScuntMissionsDashboard.jsx b/client/src/pages/ScuntMissionsDashboard/ScuntMissionsDashboard.jsx index f07a5b2c..9b07b847 100644 --- a/client/src/pages/ScuntMissionsDashboard/ScuntMissionsDashboard.jsx +++ b/client/src/pages/ScuntMissionsDashboard/ScuntMissionsDashboard.jsx @@ -2,7 +2,6 @@ import { React, useState, useEffect, useContext } from 'react'; -import { list } from '../ScuntJudgeForm/scuntTempData'; import './ScuntMissionsDashboard.scss'; import '../AccountsApproval/AccountsApproval.scss'; @@ -68,7 +67,6 @@ const ScuntCreateMissions = () => { }; const { setSnackbar } = useContext(SnackbarContext); // use Snackbar to send messages --> successfull hidden/deleted, etc. - const { darkMode } = useContext(DarkModeContext); const [newMission, setNewMission] = useState(initialMission); let keys = Object.keys(newMission); @@ -106,89 +104,87 @@ const ScuntCreateMissions = () => { }; return ( - <> -
-
-
- {missioninput.map((i) => { - return ( - { - handleInput(input, i.key); - } - // TODO: update the state var -- DONE +
+
+
+ {missioninput.map((i) => { + return ( + { + handleInput(input, i.key); } - style={{ width: '100%', flexGrow: '1' }} - description={i.des} - /> - ); - })} - { - handleInput(state, 'isHidden'); - }} - /> - { - handleInput(state, 'isJudgingStation'); - }} - /> -
-
-
-

Mission Preview

- - {newMission !== undefined ? ( - keys?.map((i) => { - return ( -
-

- {convertCamelToLabel(i)} - {': '} -

- {newMission[i] === true || newMission[i] === false ? ( -
- {newMission[i].toString()} -
- ) : ( - newMission[i].toString() - )} -
- ); - }) - ) : ( - <> - )} -
- -
+
+
+

Mission Preview

+ + {newMission !== undefined ? ( + keys?.map((i) => { + return ( +
+

+ {convertCamelToLabel(i)} + {': '} +

+ {newMission[i] === true || newMission[i] === false ? ( +
+ {newMission[i].toString()} +
+ ) : ( + newMission[i].toString() + )} +
+ ); + }) + ) : ( + <> + )}
+ +
- +
); }; @@ -429,7 +425,7 @@ const ScuntUploadMissions = () => { if (file) { fileReader.onload = function (event) { const text = event.target.result; - const { data, errors } = parseCsvString(text, csvFields); + const { data } = parseCsvString(text, csvFields); setArray(data); }; diff --git a/client/src/pages/ScuntMissionsList/ScuntMissionsList.jsx b/client/src/pages/ScuntMissionsList/ScuntMissionsList.jsx index 194e80bf..1829feb3 100644 --- a/client/src/pages/ScuntMissionsList/ScuntMissionsList.jsx +++ b/client/src/pages/ScuntMissionsList/ScuntMissionsList.jsx @@ -16,7 +16,11 @@ import { SnackbarContext } from '../../util/SnackbarProvider'; import { scuntMissionsSelector } from '../../state/scuntMissions/scuntMissionsSlice'; import useAxios from '../../hooks/useAxios'; const { axios } = useAxios(); -import star from '../../assets/misc/star-solid.svg'; +import greenCheck from '../../assets/misc/check-solid-green.svg'; +import { scuntTeamTransactionsSelector } from '../../state/scuntTeams/scuntTeamsSlice'; +import { getScuntTeamTransactions } from '../../state/scuntTeams/saga'; +import { PopupModal } from '../../components/popup/PopupModal'; +import { Button } from '../../components/button/Button/Button'; function getMissionCategories(missions) { let currentCategory = ''; @@ -32,6 +36,7 @@ function getMissionCategories(missions) { const PageScuntMissionsList = () => { const { user } = useSelector(userSelector); + const loggedIn = useSelector(loggedInSelector); const { setSnackbar } = useContext(SnackbarContext); const leader = user?.userType === 'leadur'; const { scuntSettings, loading } = useSelector(scuntSettingsSelector); @@ -40,16 +45,14 @@ const PageScuntMissionsList = () => { const dispatch = useDispatch(); useEffect(() => { - if (scuntSettings !== undefined) { - setRevealMissions(scuntSettings[0]?.revealMissions); - } + if (scuntSettings?.revealMissions) setRevealMissions(true); }, [scuntSettings]); useEffect(() => { - dispatch(getScuntMissions({ showHidden: false, setSnackbar })); - }, []); + dispatch(getScuntMissions({ showHidden: false })); + }, [dispatch]); - if (revealMissions !== true && !leader) { + if ((revealMissions !== true && !leader) || !loggedIn) { return ( <>
@@ -72,9 +75,121 @@ const PageScuntMissionsList = () => { ); }; +const ReportMission = () => { + const [click, setClick] = useState(false); + + return ( + <> + + + +
} + isSecondary + onClick={() => { + setClick(true); + }} + > + + ); +}; + +const ReportMissionPopup = () => { + const initialFormData = { + optionalName: '', + reportReason: '', + preferredAction: '', + }; + const [formData, setFormData] = useState(initialFormData); + const { setSnackbar } = useContext(SnackbarContext); + const [clearText, setClearText] = useState(false); + + const handleInputChange = (text, field) => { + let newFormData = { ...formData }; + newFormData[field] = text; + setFormData(newFormData); + }; + + async function handleSubmit(text) { + if (formData.reportReason?.length <= 0) { + setSnackbar('Please provide a reason for reporting', true); + } else if (formData.preferredAction?.length <= 0) { + setSnackbar('Please provide a preferred action', true); + } else { + // using faq services + const reqObj = { + email: formData.name, + question: + 'Report Reason: ' + + formData.reportReason + + ' | Preferred Action: ' + + formData.preferredAction, + category: 'Scunt Reports', + }; + + try { + const result = await axios.post('/faq/create', reqObj); + if (result.status !== 200) { + setSnackbar('There was an error submitting your report' + result, true); + } else { + setSnackbar('Thank you for submitting your report!', false); + setClearText(true); + } + } catch (error) { + return error; + } + } + } + + return ( +
+

Report Mission

+

+ Your report will be shared with F!rosh Execs, we aim to review reports within 30 minutes. +

+ +
+ handleInputChange(text, 'optionalName')} + inputType={'text'} + clearText={clearText} + setClearText={setClearText} + /> + handleInputChange(text, 'reportReason')} + inputType={'textArea'} + clearText={clearText} + setClearText={setClearText} + /> + handleInputChange(text, 'preferredAction')} + inputType={'textArea'} + placeholder={'Remove the item'} + clearText={clearText} + setClearText={setClearText} + /> +
+ +
+ +
+
+ ); +}; + const PageScuntMissionsListShow = () => { const { user } = useSelector(userSelector); const { missions } = useSelector(scuntMissionsSelector); + const { scuntTeamTransactions } = useSelector(scuntTeamTransactionsSelector); const [mission, setMission] = useState(undefined); const [searchedMissions, setSearchedMissions] = useState(missions); const [clearText, setClearText] = useState(false); @@ -82,6 +197,28 @@ const PageScuntMissionsListShow = () => { const [selectedSort, setSelectedSort] = useState('ID'); const [missionStatus, setMissionStatus] = useState(undefined); const loggedIn = useSelector(loggedInSelector); + const [completedMissions, setCompletedMissions] = useState({}); + + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getScuntTeamTransactions({ teamNumber: user?.scuntTeam })); + }, [dispatch]); + + useEffect(() => { + if (scuntTeamTransactions?.length) { + setCompletedMissions( + scuntTeamTransactions.reduce((missions, transaction) => { + if (transaction?.missionNumber > 0) { + // -1 for bribes for deleted points + missions[transaction?.missionNumber] = transaction?.points; + } + + return missions; + }, {}), + ); + } + }, [scuntTeamTransactions]); useEffect(() => { setMission(undefined); @@ -167,9 +304,14 @@ const PageScuntMissionsListShow = () => { Don't forget to bribe the judges!
- judging station indication -

These indicate Judging Stations, photo/video evidence is not accepted!

+ judging station indication +

These indicate completed missions!

+
@@ -245,7 +387,12 @@ const PageScuntMissionsListShow = () => { setClearText(true); }} > - +
) : ( searchedMissions.map((mission) => { @@ -257,13 +404,17 @@ const PageScuntMissionsListShow = () => { setMission(mission); }} > - +
); if (previousCategory !== mission?.category) { previousCategory = mission?.category; return ( -
+

{mission?.category}

{missionEntry} @@ -279,16 +430,12 @@ const PageScuntMissionsListShow = () => {

No search results

) : mission === undefined ? (
- ) : ( - <> - )} + ) : null}
{!loggedIn ? (

To see mission status and mission QR code please login to your account.

- ) : ( - <> - )} + ) : null} {loggedIn && mission !== undefined ? ( missionStatus?.completed ? ( <> @@ -302,12 +449,8 @@ const PageScuntMissionsListShow = () => {

- ) : ( - <> - ) - ) : ( - <> - )} + ) : null + ) : null} {loggedIn && user?.scuntTeam && mission !== undefined ? (
{ backgroundColor="white" />
- ) : ( - <> - )} + ) : null}
); }; diff --git a/client/src/pages/ScuntMissionsList/ScuntMissionsList.scss b/client/src/pages/ScuntMissionsList/ScuntMissionsList.scss index e3ad92f3..1aebe51e 100644 --- a/client/src/pages/ScuntMissionsList/ScuntMissionsList.scss +++ b/client/src/pages/ScuntMissionsList/ScuntMissionsList.scss @@ -70,7 +70,6 @@ justify-content: center; align-items: center; - margin: 20px 0; padding: 0 25%; font-size: 12px; @@ -87,3 +86,24 @@ margin: 5px 20px; color: var(--text-dynamic); } + +.scunt-report-popup-button { + display: flex; + align-items: center; + justify-content: center; + + font-size: 16px; +} + +.scunt-report-popup-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.scunt-report-input { + display: flex; + flex-direction: column; + width: 100%; +} diff --git a/client/src/reducer.jsx b/client/src/reducer.jsx index da961913..c33485b1 100644 --- a/client/src/reducer.jsx +++ b/client/src/reducer.jsx @@ -3,16 +3,18 @@ import userReducer from './state/user/userSlice'; import accountsReducer from './state/accounts/accountSlice'; import announcementsReducer from './state/announcements/announcementsSlice'; import froshReducer from './state/frosh/froshSlice'; -// import scuntSettingsReducer from './state/scuntSettings/scuntSettingsSlice'; -// import scuntMissionsReducer from './state/scuntMissions/scuntMissionsSlice'; +import scuntSettingsReducer from './state/scuntSettings/scuntSettingsSlice'; +import scuntMissionsReducer from './state/scuntMissions/scuntMissionsSlice'; +import scuntTeamsReducer from './state/scuntTeams/scuntTeamsSlice'; const rootReducer = combineReducers({ userReducer, accountsReducer, froshReducer, - // scuntSettingsReducer, - // scuntMissionsReducer, + scuntSettingsReducer, + scuntMissionsReducer, announcementsReducer, + scuntTeamsReducer, }); export default rootReducer; diff --git a/client/src/state/frosh/saga.jsx b/client/src/state/frosh/saga.jsx index 1bd6c546..7f8fc6b4 100644 --- a/client/src/state/frosh/saga.jsx +++ b/client/src/state/frosh/saga.jsx @@ -105,6 +105,23 @@ export function* preKitPickUpSaga({ payload: { userID } }) { } } +export const getFood = createAction('getFoodSaga'); + +export function* getFoodSaga({ payload: { userID } }) { + const { axios } = useAxios(); + try { + yield put(preKitPickUpStart()); + const date = new Date(); + const result = yield call(axios.put, '/qr/food', { + userID, + }); + yield put(preKitPickUpSuccess(result?.data?.frosh)); + } catch (error) { + console.error(error); + yield put(preKitPickUpFailure(error?.response?.data?.errorMessage)); + } +} + export default function* froshSaga() { yield takeLeading(getFroshList.type, getFroshListSaga); yield takeLeading(redistributeFrosh.type, redistributeFroshSaga); @@ -112,4 +129,5 @@ export default function* froshSaga() { yield takeLeading(preKitPickUp.type, preKitPickUpSaga); yield takeLeading(searchFroshList.type, searchFroshListSaga); yield takeLeading(clearFroshList.type, clearFroshListSaga); + yield takeLeading(getFood.type, getFoodSaga); } diff --git a/client/src/state/scuntMissions/saga.jsx b/client/src/state/scuntMissions/saga.jsx index c88d5311..fa922925 100644 --- a/client/src/state/scuntMissions/saga.jsx +++ b/client/src/state/scuntMissions/saga.jsx @@ -15,19 +15,10 @@ export function* getScuntMissionsSaga({ payload: { showHidden, setSnackbar } }) yield put(getScuntMissionsStart()); const result = yield call(axios.get, `/scunt-missions/?showHidden=${showHidden}`); yield put(getScuntMissionsSuccess(result.data.missions)); - // setSnackbar("Successfully retrieved missions") - } catch (e) { - yield put(getScuntMissionsFailure(e)); - setSnackbar( - e.response.data.message - ? e.response.data.message.toString() - : e.response.data.errorMessage - ? e.response.data.errorMessage.toString() - : e.response.data - ? e.response.data.toString() - : 'Uh oh, something went wrong! Please try again later.', - true, - ); + setSnackbar && setSnackbar('Successfully retrieved missions'); + } catch (error) { + yield put(getScuntMissionsFailure(error.response.data?.errorMessage)); + setSnackbar && setSnackbar(error.response.data?.errorMessage, true); } } @@ -39,20 +30,11 @@ export function* createMultipleMissionsSaga({ payload: { array, setSnackbar } }) yield put(getScuntMissionsStart()); const result = yield call(axios.post, 'scunt-missions/bulk', { array }); yield put(getScuntMissionsSuccess(result.data.missions)); - setSnackbar('Successfully uploaded missions!', false); - } catch (e) { - console.error(e); - yield put(getScuntMissionsFailure(e)); - setSnackbar( - e.response.data.message - ? e.response.data.message.toString() - : e.response.data.errorMessage - ? e.response.data.errorMessage.toString() - : e.response.data - ? e.response.data.toString() - : 'Uh oh, something went wrong! Please try again later.', - true, - ); + setSnackbar && setSnackbar('Successfully uploaded missions!', false); + } catch (error) { + console.error(error); + yield put(getScuntMissionsFailure(error)); + setSnackbar && setSnackbar(error.response.data?.errorMessage, true); } } diff --git a/client/src/state/scuntSettings/saga.jsx b/client/src/state/scuntSettings/saga.jsx index 772b5ae1..13e8fd6b 100644 --- a/client/src/state/scuntSettings/saga.jsx +++ b/client/src/state/scuntSettings/saga.jsx @@ -8,20 +8,26 @@ import { setScuntSettingsStart, setScuntSettingsSuccess, setScuntSettingsFailure, + getJudgesStart, + getJudgesSuccess, + getJudgesFailure, + giveJudgeBribePointsStart, + giveJudgeBribePointsSuccess, + giveJudgeBribePointsFailure, } from './scuntSettingsSlice'; import useAxios from '../../hooks/useAxios'; export const getScuntSettings = createAction('getScuntSettingsSaga'); -export function* getScuntSettingsSaga() { +export function* getScuntSettingsSaga({ payload: setSnackbar }) { const { axios } = useAxios(); try { yield put(getScuntSettingsStart()); const result = yield call(axios.get, '/scunt-game-controls'); - yield put(getScuntSettingsSuccess(result.data.settings)); } catch (error) { - yield put(getScuntSettingsFailure(error.response.data)); + yield put(getScuntSettingsFailure(error?.response?.data?.errorMessage)); + setSnackbar && setSnackbar(error?.response?.data?.errorMessage, true); } } @@ -65,40 +71,49 @@ export function* setGameSettingsSaga({ yield put(setScuntSettingsSuccess(result.data.settings)); } catch (error) { console.error(error); - setSnackbar( - error.response?.data?.message - ? error.response?.data?.message.toString() - : error.response?.data - ? error.response?.data.toString() - : error.toString(), - true, - ); - console.error(error); - yield put(setScuntSettingsFailure(error.response.data)); + setSnackbar(error.response?.data?.errorMessage, true); + yield put(setScuntSettingsFailure(error.response?.data?.errorMessage)); } } -export const shuffleScuntTeams = createAction('shuffleScuntTeamsSaga'); +export const getJudges = createAction('getJudgesSaga'); -export function* shuffleScuntTeamsSaga({ payload: setSnackbar }) { +export function* getJudgesSaga({ payload: setSnackbar }) { const { axios } = useAxios(); try { - yield call(axios.post, '/scunt-teams/shuffle'); - setSnackbar('Teams shuffled successfully!', false); + yield put(getJudgesStart()); + const result = yield call(axios.get, '/scunt-teams/judges'); + yield put(getJudgesSuccess(result.data.judges)); + } catch (error) { + yield put(getJudgesFailure(error?.response?.data?.errorMessage)); + setSnackbar && setSnackbar(error?.response?.data?.errorMessage, true); + } +} + +export const giveJudgeBribePoints = createAction('giveJudgeBribePointsSaga'); + +export function* giveJudgeBribePointsSaga({ + payload: { judgeUserId, points, isAddPoints, setSnackbar }, +}) { + const { axios } = useAxios(); + try { + yield put(giveJudgeBribePointsStart()); + const result = yield call(axios.post, '/scunt-teams/transaction/refill-bribe', { + judgeUserId, + points, + isAddPoints, + }); + setSnackbar(result.data.message); + yield put(giveJudgeBribePointsSuccess(result.data.judges)); } catch (error) { - setSnackbar( - error.response?.data?.message - ? error.response?.data?.message.toString() - : error.response?.data - ? error.response?.data.toString() - : error.toString(), - true, - ); + yield put(giveJudgeBribePointsFailure(error?.response?.data?.errorMessage)); + setSnackbar && setSnackbar(error?.response?.data?.errorMessage, true); } } export default function* scuntSettingsSaga() { yield takeLeading(getScuntSettings.type, getScuntSettingsSaga); yield takeLeading(setScuntSettings.type, setGameSettingsSaga); - yield takeLeading(shuffleScuntTeams.type, shuffleScuntTeamsSaga); + yield takeLeading(getJudges.type, getJudgesSaga); + yield takeLeading(giveJudgeBribePoints.type, giveJudgeBribePointsSaga); } diff --git a/client/src/state/scuntSettings/scuntSettingsSlice.jsx b/client/src/state/scuntSettings/scuntSettingsSlice.jsx index ea37e9c2..2e8c4028 100644 --- a/client/src/state/scuntSettings/scuntSettingsSlice.jsx +++ b/client/src/state/scuntSettings/scuntSettingsSlice.jsx @@ -5,6 +5,7 @@ export const initialState = { loading: false, error: null, scuntSettings: undefined, + judges: [], }; const scuntSettingsSlice = createSlice({ @@ -38,6 +39,32 @@ const scuntSettingsSlice = createSlice({ state.loading = false; state.error = error; }, + getJudgesStart: (state) => { + state.loading = true; + state.error = null; + }, + getJudgesSuccess: (state, { payload: judges }) => { + state.loading = false; + state.error = null; + state.judges = judges; + }, + getJudgesFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, + giveJudgeBribePointsStart: (state) => { + state.loading = true; + state.error = null; + }, + giveJudgeBribePointsSuccess: (state, { payload: judges }) => { + state.loading = false; + state.error = null; + state.judges = judges; + }, + giveJudgeBribePointsFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, }, }); @@ -48,6 +75,12 @@ export const { setScuntSettingsStart, setScuntSettingsSuccess, setScuntSettingsFailure, + getJudgesStart, + getJudgesSuccess, + getJudgesFailure, + giveJudgeBribePointsStart, + giveJudgeBribePointsSuccess, + giveJudgeBribePointsFailure, } = scuntSettingsSlice.actions; export default scuntSettingsSlice.reducer; @@ -76,12 +109,17 @@ export const maxAmountPointsPercentSelector = createSelector( ({ scuntSettings }) => scuntSettings?.maxAmountPointsPercent, ); -export const showDiscordLinkSelector = createSelector( - scuntSettingsReducerSelector, - ({ scuntSettings }) => scuntSettings?.showDiscordLink, -); +// export const showDiscordLinkSelector = createSelector( +// scuntSettingsReducerSelector, +// ({ scuntSettings }) => scuntSettings?.showDiscordLink, +// ); + +// export const discordLinkSelector = createSelector( +// scuntSettingsReducerSelector, +// ({ scuntSettings }) => scuntSettings?.discordLink, +// ); -export const discordLinkSelector = createSelector( +export const scuntJudgeSelector = createSelector( scuntSettingsReducerSelector, - ({ scuntSettings }) => scuntSettings?.discordLink, + ({ judges, loading, error }) => ({ judges, loading, error }), ); diff --git a/client/src/state/scuntTeams/saga.jsx b/client/src/state/scuntTeams/saga.jsx new file mode 100644 index 00000000..a0fd00d8 --- /dev/null +++ b/client/src/state/scuntTeams/saga.jsx @@ -0,0 +1,179 @@ +import { createAction } from '@reduxjs/toolkit'; +import { put, call, takeLeading } from 'redux-saga/effects'; + +import { + getScuntTeamsStart, + getScuntTeamsSuccess, + getScuntTeamsFailure, + setScuntTeamsStart, + setScuntTeamsSuccess, + setScuntTeamsFailure, + getScuntTeamTransactionsStart, + getScuntTeamTransactionsSuccess, + getScuntTeamTransactionsFailure, + updateScuntTeamsStart, + updateScuntTeamsSuccess, + updateScuntTeamsFailure, + addPointsStart, + addPointsSuccess, + addPointsFailure, + subtractPointsStart, + subtractPointsSuccess, + subtractPointsFailure, + getMissionStatusStart, + getMissionStatusSuccess, + getMissionStatusFailure, +} from './scuntTeamsSlice'; + +import { + updateUserInfoFailure, + updateUserInfoStart, + updateUserInfoSuccess, +} from '../user/userSlice'; + +import useAxios from '../../hooks/useAxios'; + +export const getScuntTeams = createAction('getScuntTeamsSaga'); + +export function* getScuntTeamsSaga({ payload: setSnackbar }) { + const { axios } = useAxios(); + try { + yield put(getScuntTeamsStart()); + const result = yield call(axios.get, '/scunt-teams'); + + yield put(getScuntTeamsSuccess(result.data.scuntTeams)); + } catch (error) { + yield put(getScuntTeamsFailure(error.response.data.errorMessage)); + setSnackbar && setSnackbar(error.response.data.errorMessage, true); + } +} + +export const getScuntTeamTransactions = createAction('getScuntTeamSaga'); + +export function* getScuntTeamSaga({ payload: { teamNumber, setSnackbar } }) { + const { axios } = useAxios(); + try { + yield put(getScuntTeamTransactionsStart()); + const result = yield call(axios.post, `/scunt-teams/transactions`, { teamNumber }); + yield put(getScuntTeamTransactionsSuccess(result.data?.transactions)); + } catch (error) { + yield put(getScuntTeamTransactionsFailure(error.response.data.errorMessage)); + setSnackbar && setSnackbar(error.response.data.errorMessage, true); + } +} + +export const setScuntTeams = createAction('setGameTeamsSaga'); + +export function* setGameTeamsSaga({ payload: { scuntTeams, setSnackbar } }) { + const { axios } = useAxios(); + try { + yield put(setScuntTeamsStart()); + const result = yield call(axios.put, '/scunt-teams/rename-teams', { + teamObjs: scuntTeams, + }); + setSnackbar('Scunt Teams Updated!'); + console.log(result); + yield put(setScuntTeamsSuccess(result.data.scuntTeams)); + } catch (error) { + console.error(error); + setSnackbar(error.response?.data?.errorMessage, true); + yield put(setScuntTeamsFailure(error.response.data)); + } +} + +export const shuffleScuntTeams = createAction('shuffleScuntTeamsSaga'); + +export function* shuffleScuntTeamsSaga({ payload: setSnackbar }) { + const { axios } = useAxios(); + try { + yield put(updateScuntTeamsStart()); + const result = yield call(axios.post, '/scunt-teams/shuffle'); + yield put(updateScuntTeamsSuccess(result.data.scuntTeams)); + setSnackbar(result.data.message, false); + } catch (error) { + updateScuntTeamsFailure(error.response?.data?.errorMessage); + setSnackbar(error.response?.data?.errorMessage, true); + } +} + +export const changeScuntTeam = createAction('changeScuntTeamSaga'); + +export function* changeScuntTeamSaga({ payload: { teamNumber, setSnackbar } }) { + const { axios } = useAxios(); + try { + yield put(updateUserInfoStart()); + + const result = yield call(axios.post, '/scunt-teams/update-team', { teamNumber }); + setSnackbar('Team updated successfully!', false); + yield put(updateUserInfoSuccess(result.data.user)); + } catch (error) { + setSnackbar(error.response?.data?.errorMessage, true); + yield put(updateUserInfoFailure(error.response?.data?.errorMessage)); + } +} + +export const addPoints = createAction('addPointsSaga'); + +export function* addPointsSaga({ payload: { teamNumber, points, missionNumber, setSnackbar } }) { + const { axios } = useAxios(); + try { + yield put(addPointsStart()); + const result = yield call(axios.post, '/scunt-teams/transaction/add', { + teamNumber, + points, + missionNumber, + }); + yield put(addPointsSuccess(result.data.scuntTeams)); + setSnackbar && setSnackbar(result?.data?.message, false); + } catch (error) { + yield put(addPointsFailure(error.response?.data?.errorMessage)); + setSnackbar && setSnackbar(error.response?.data?.errorMessage, true); + } +} + +export const subtractPoints = createAction('subtractPointsSaga'); + +export function* subtractPointsSaga({ payload: { teamNumber, points, setSnackbar } }) { + const { axios } = useAxios(); + try { + yield put(subtractPointsStart()); + const result = yield call(axios.post, '/scunt-teams/transaction/subtract', { + teamNumber, + points, + }); + yield put(subtractPointsSuccess(result.data.scuntTeams)); + setSnackbar && setSnackbar('Points subtracted successfully!', false); + } catch (error) { + yield put(subtractPointsFailure(error.response?.data?.errorMessage)); + setSnackbar && setSnackbar(error.response?.data?.errorMessage, true); + } +} + +export const getMissionStatus = createAction('getMissionStatusSaga'); + +export function* getMissionStatusSaga({ payload: { teamNumber, missionNumber, setSnackbar } }) { + const { axios } = useAxios(); + try { + yield put(getMissionStatusStart()); + const result = yield call(axios.post, '/scunt-teams/transaction/check', { + teamNumber, + missionNumber, + }); + yield put(getMissionStatusSuccess(result.data?.missionStatus)); + setSnackbar && setSnackbar('Mission status retrieved successfully!', false); + } catch (error) { + yield put(getMissionStatusFailure(error.response?.data?.errorMessage)); + setSnackbar && setSnackbar(error.response?.data?.errorMessage, true); + } +} + +export default function* scuntTeamsSaga() { + yield takeLeading(getScuntTeams.type, getScuntTeamsSaga); + yield takeLeading(getScuntTeamTransactions.type, getScuntTeamSaga); + yield takeLeading(setScuntTeams.type, setGameTeamsSaga); + yield takeLeading(shuffleScuntTeams.type, shuffleScuntTeamsSaga); + yield takeLeading(changeScuntTeam.type, changeScuntTeamSaga); + yield takeLeading(subtractPoints.type, subtractPointsSaga); + yield takeLeading(getMissionStatus.type, getMissionStatusSaga); + yield takeLeading(addPoints.type, addPointsSaga); +} diff --git a/client/src/state/scuntTeams/scuntTeamsSlice.jsx b/client/src/state/scuntTeams/scuntTeamsSlice.jsx new file mode 100644 index 00000000..fa78ed69 --- /dev/null +++ b/client/src/state/scuntTeams/scuntTeamsSlice.jsx @@ -0,0 +1,151 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { createSelector } from 'reselect'; + +export const initialState = { + loading: false, + error: null, + scuntTeamTransactions: [], + scuntTeam: {}, + missionStatus: null, +}; + +const scuntTeamsSlice = createSlice({ + name: 'scuntTeamsReducer', + initialState, + reducers: { + getScuntTeamsStart: (state) => { + state.loading = true; + state.error = null; + }, + getScuntTeamsSuccess: (state, { payload: scuntTeams }) => { + state.loading = false; + state.error = null; + state.scuntTeams = scuntTeams; + }, + getScuntTeamsFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, + setScuntTeamsStart: (state) => { + state.loading = true; + state.error = null; + }, + setScuntTeamsSuccess: (state, { payload: scuntTeams }) => { + state.loading = false; + state.error = null; + state.scuntTeams = scuntTeams; + }, + setScuntTeamsFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, + getScuntTeamTransactionsStart: (state) => { + state.loading = true; + state.error = null; + }, + getScuntTeamTransactionsSuccess: (state, { payload: scuntTeamTransactions }) => { + state.loading = false; + state.error = null; + state.scuntTeamTransactions = scuntTeamTransactions; + }, + getScuntTeamTransactionsFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, + updateScuntTeamsStart: (state) => { + state.loading = true; + state.error = null; + }, + updateScuntTeamsSuccess: (state, { payload: scuntTeams }) => { + state.loading = false; + state.error = null; + state.scuntTeams = scuntTeams; + }, + updateScuntTeamsFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, + addPointsStart: (state) => { + state.loading = true; + state.error = null; + }, + addPointsSuccess: (state, { payload: scuntTeams }) => { + state.loading = false; + state.error = null; + state.scuntTeams = scuntTeams; + }, + addPointsFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, + subtractPointsStart: (state) => { + state.loading = true; + state.error = null; + }, + subtractPointsSuccess: (state, { payload: scuntTeams }) => { + state.loading = false; + state.error = null; + state.scuntTeams = scuntTeams; + }, + subtractPointsFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, + getMissionStatusStart: (state) => { + state.loading = true; + state.error = null; + }, + getMissionStatusSuccess: (state, { payload: missionStatus }) => { + state.loading = false; + state.error = null; + state.missionStatus = missionStatus; + }, + getMissionStatusFailure: (state, { payload: error }) => { + state.loading = false; + state.error = error; + }, + }, +}); + +export const { + getScuntTeamsStart, + getScuntTeamsSuccess, + getScuntTeamsFailure, + setScuntTeamsStart, + setScuntTeamsSuccess, + setScuntTeamsFailure, + getScuntTeamTransactionsStart, + getScuntTeamTransactionsSuccess, + getScuntTeamTransactionsFailure, + updateScuntTeamsStart, + updateScuntTeamsSuccess, + updateScuntTeamsFailure, + addPointsStart, + addPointsSuccess, + addPointsFailure, + subtractPointsStart, + subtractPointsSuccess, + subtractPointsFailure, + getMissionStatusStart, + getMissionStatusSuccess, + getMissionStatusFailure, +} = scuntTeamsSlice.actions; + +export default scuntTeamsSlice.reducer; + +export const scuntTeamsReducerSelector = (state) => state[scuntTeamsSlice.name]; + +export const scuntTeamsSelector = createSelector( + scuntTeamsReducerSelector, + ({ scuntTeams, loading, error }) => ({ scuntTeams, loading, error }), +); + +export const scuntTeamTransactionsSelector = createSelector( + scuntTeamsReducerSelector, + ({ scuntTeamTransactions, loading, error }) => ({ scuntTeamTransactions, loading, error }), +); + +export const missionStatusSelector = createSelector( + scuntTeamsReducerSelector, + ({ missionStatus, loading, error }) => ({ missionStatus, loading, error }), +); diff --git a/client/src/util/pages.jsx b/client/src/util/pages.jsx index 0896229a..08784e0a 100644 --- a/client/src/util/pages.jsx +++ b/client/src/util/pages.jsx @@ -18,21 +18,21 @@ import { PasswordReset } from '../pages/PasswordReset/PasswordReset'; import { PageFroshInfoTable } from '../pages/FroshInfoTable/FroshInfoTable'; import { PageFroshRedistribution } from '../pages/FroshRedistribution/FroshRedistribution'; import { PageScopeRequest } from '../pages/ScopeRequest/ScopeRequest'; -// import { PageScuntJudgeForm } from '../pages/ScuntJudgeForm/ScuntJudgeForm'; -// import { PageScuntMissionsList } from '../pages/ScuntMissionsList/ScuntMissionsList'; -// import { PageScuntHome } from '../pages/ScuntHome/ScuntHome'; -// import { PageScuntRules } from '../pages/ScuntRules/ScuntRules'; +import { PageScuntJudgeForm } from '../pages/ScuntJudgeForm/ScuntJudgeForm'; +import { PageScuntMissionsList } from '../pages/ScuntMissionsList/ScuntMissionsList'; +import { PageScuntHome } from '../pages/ScuntHome/ScuntHome'; +import { PageScuntRules } from '../pages/ScuntRules/ScuntRules'; import { PageTimelineAdmin } from '../pages/TimelineAdmin/TimelineAdmin'; import { PageAnnounceDash } from '../pages/AnnouncementDashboard/AnnounceDash'; import { PageUnsubscribe } from '../pages/Unsubscribe/Unsubscribe'; import { PageResubscribe } from '../pages/Resubscribe/Resubscribe'; -// import { ScuntJudges } from '../pages/ScuntJudges/ScuntJudges'; -// import { ScuntLeaderboard } from '../pages/ScuntLeaderboard/ScuntLeaderboard'; +import { ScuntJudges } from '../pages/ScuntJudges/ScuntJudges'; +import { ScuntLeaderboard } from '../pages/ScuntLeaderboard/ScuntLeaderboard'; import { FroshRetreat } from '../pages/FroshRetreat/FroshRetreat'; import { PagePaymentSuccess } from '../pages/PagePaymentSuccess/PagePaymentSuccess'; -// import { ScuntGameSettings } from '../pages/ScuntGameSettings/ScuntGameSettings'; -// import { PageScuntMissionsDashboard } from '../pages/ScuntMissionsDashboard/ScuntMissionsDashboard'; -// import { ScuntTransactions } from '../pages/ScuntTransactions/ScuntTransactions'; +import { ScuntGameSettings } from '../pages/ScuntGameSettings/ScuntGameSettings'; +import { PageScuntMissionsDashboard } from '../pages/ScuntMissionsDashboard/ScuntMissionsDashboard'; +import { ScuntTransactions } from '../pages/ScuntTransactions/ScuntTransactions'; import { PageEmailConfirmed } from '../pages/EmailConfirmed/EmailConfirmed'; export const pages = { @@ -129,16 +129,16 @@ export const pages = { path: '/maintenance', includeFooter: false, }, - { - label: 'Registration', - component: ( - - - - ), - path: '/registration', - includeFooter: true, - }, + // { + // label: 'Registration', + // component: ( + // + // + // + // ), + // path: '/registration', + // includeFooter: true, + // }, { label: 'Registration Success', component: , @@ -156,11 +156,11 @@ export const pages = { ), path: '/registration-success-retreat', }, - { - label: 'sign-up', - component: , - path: '/sign-up', - }, + // { + // label: 'sign-up', + // component: , + // path: '/sign-up', + // }, { label: 'profile-edit', component: ( @@ -251,86 +251,86 @@ export const pages = { }, ], scunt: [ - // { - // label: 'Scunt', - // scuntLabel: 'Home', - // component: , - // path: '/scunt', - // includeFooter: true, - // }, - // { - // label: 'Judges', - // scuntLabel: 'Judges', - // component: , - // path: '/scunt-judges', - // includeFooter: true, - // }, - // { - // label: 'Missions', - // scuntLabel: 'Missions', - // component: , - // path: '/scunt-missions', - // includeFooter: true, - // }, - // { - // label: 'Leaderboard', - // scuntLabel: 'Leaderboard', - // component: , - // path: '/scunt-leaderboard', - // includeFooter: true, - // }, - // { - // label: 'Rules', - // scuntLabel: 'Rules', - // component: , - // path: '/scunt-rules', - // includeFooter: true, - // }, + { + label: 'Scunt', + scuntLabel: 'Home', + component: , + path: '/scunt', + includeFooter: true, + }, + { + label: 'Judges', + scuntLabel: 'Judges', + component: , + path: '/scunt-judges', + includeFooter: true, + }, + { + label: 'Missions', + scuntLabel: 'Missions', + component: , + path: '/scunt-missions', + includeFooter: true, + }, + { + label: 'Leaderboard', + scuntLabel: 'Leaderboard', + component: , + path: '/scunt-leaderboard', + includeFooter: true, + }, + { + label: 'Rules', + scuntLabel: 'Rules', + component: , + path: '/scunt-rules', + includeFooter: true, + }, ], scuntHidden: [ - // { - // label: 'Scunt Judge Form', - // component: ( - // - // - // - // ), - // path: '/scunt-judge-form', - // includeFooter: true, - // }, - // { - // label: 'start-scunt', - // component: ( - // - // - // - // ), - // path: '/scunt-game-controls', - // }, - // { - // label: 'Scunt Missions Dashboard', - // component: ( - // - // - // - // ), - // path: '/scunt-missions-dashboard', - // }, - // { - // label: 'Scunt Point Transactions', - // path: '/scunt-transactions', - // component: ( - // - // - // - // ), - // }, + { + label: 'Scunt Judge Form', + component: ( + + + + ), + path: '/scunt-judge-form', + includeFooter: true, + }, + { + label: 'start-scunt', + component: ( + + + + ), + path: '/scunt-game-controls', + }, + { + label: 'Scunt Missions Dashboard', + component: ( + + + + ), + path: '/scunt-missions-dashboard', + }, + { + label: 'Scunt Point Transactions', + path: '/scunt-transactions', + component: ( + + + + ), + }, ], }; diff --git a/client/src/util/scunt-constants.jsx b/client/src/util/scunt-constants.jsx index 85385b89..f3564ffd 100644 --- a/client/src/util/scunt-constants.jsx +++ b/client/src/util/scunt-constants.jsx @@ -2,24 +2,21 @@ export const okayToInviteToScunt = false; export const scuntDiscord = 'https://discord.gg/mRutbwuCK9'; export const scuntDate = 'September 7, 2022 18:00:00'; export const aboutScunt = ` -

Scunt

-

What is Scunt?

+

The H!unt

+

What is S!cavenger H!unt?

- Scunt is the best part of F!rosh Week (we promise we aren’t biased)! It’s a chaos filled event where you and your team compete against other F!rosh to get as many points as you possibly can. Your team gains points by completing missions and getting them judged by our super judgy judges (judging stations are located in the Pit and on the GB steps). The top three teams mayyyy also get something special on top of well-deserved bragging rights ;) -

-

Important Info

-

- You will be assigned a Scunt team (different from your F!rosh group) on Wednesday on the F!rosh week website. Please meet with your team on King’s College Road (outside of Sandford Fleming) at 5:30PM. We’ve attached a map that shows the location each team will be meeting at and our Scunt HLs will also have signs. Please do not be late, teams will be moving off of campus once the event begins. If you have any questions contact us at scunt@orientation.skule.ca. + The H!unt is the best part of F!rosh Week (we promise we aren’t biased)! It’s a chaos filled event where you and your team compete against other F!rosh to get as many points as you possibly can. Your team gains points by completing missions and getting them judged by our super judgy judges (judging stations are located in the Pit). The top three teams mayyyy also get something special on top of well-deserved bragging rights ;)

+ `; export const rules = { start: [ { title: 'Eligibility', - sub: 'To compete in the Havenger Scunt, one must be:', + sub: 'To compete in the S!cavenger H!unt, one must be:', items: [ 'Human, or near human (Engineering Science students will be accepted).', - 'A F!rosh (2T6!).', + 'A F!rosh (2T7!).', 'Currently enrolled within the Faculty of Applied Science and Engineering at the University of Toronto.', 'Have officially registered for the event via F!rosh Week 2T3.', ], @@ -35,7 +32,7 @@ export const rules = { }, { title: 'Teams', - sub: 'The team structure of Havenger Scunt will be as follows:', + sub: 'The team structure of S!cavenger H!unt will be as follows:', items: [ 'Contestants will be assigned randomly to 1 of 10 teams to approximate fairness prior to the event.', 'Each team will consist of 2 Head Leedurs and a number of Leedurs.', @@ -44,11 +41,11 @@ export const rules = { }, { title: 'Event Schedule', - sub: 'The timing of Havenger Scunt will be as follows:', + sub: 'The timing of S!cavenger H!unt will be as follows:', items: [ - 'The event shall begin on Wednesday, September 7th at 6:00 PM EST. At this time, orientation.skule.ca/scunt will go live with the list, as will all the commands on our Discord server. Oh yeah and the judges will rise from their upper year slumber too.', + 'The event shall begin on Wednesday, September 6th at 6:00 PM EST. At this time, orientation.skule.ca/scunt will go live with the list. Oh yeah and the judges will rise from their upper year slumber too.', 'The Royal Wedding will occur at approximately 10:00 PM', - 'The event will end on Wednesday, September 7th at 11:00 PM EST. There will be a 15-minute warning announcement.', + 'The event will end on Wednesday, September 6th at 11:00 PM EST. There will be a 15-minute warning announcement.', ], }, { @@ -61,7 +58,7 @@ export const rules = { '***The item must be on the list.***', 'Said item must have been completed by (at minimum) one freshman (F!rosh) from said team. Items completed by Leedurs alone will be ineligible for scoring.
  1. Leedurs may present digital evidence to a Judge to submit an item for their team, but there must either be a F!rosh featured in the photo/video, or proof that it was sent to the Leedur by a F!rosh.
', '***The item must be on the list.***', - 'It is encouraged to let Judges keep physical items brought in person (like a bigass fucking dildo) as part of the Havenger Scunt unless the items have a significant sentimental value.', + 'It is encouraged to let Judges keep physical items brought in person (like a bigass fucking dildo) as part of the S!cavenger H!unt unless the items have a significant sentimental value.', '***The item must be on the list.***', 'If there is any mess created by performing an item, it must be cleaned up or you will not get the points.', '***The item must be on the list.***', @@ -77,7 +74,7 @@ export const rules = { title: 'Judging', items: [ 'Items must be submitted in person to a judge, starting at 6:00 PM and ending at 11:00 PM as with the rest of the event.', - 'There will be sixteen (16) total judges for Havenger Scunt.
  1. Occasionally, members of the F!rosh Week Executive Team may stand in as judges, during busy periods.
', + 'There will be sixteen (16) total judges for S!cavenger H!unt.
  1. Occasionally, members of the F!rosh Week Executive Team may stand in as judges, during busy periods.
', 'There will be two (2) Judging Stations, one in the Pit and another on the steps of Galbraith Building. Each station will have eight (8) judges.
  1. Partway through the evening, the judges will swap stations.
', 'A maximum of three (3) items may be submitted to a single judge by one person at once. This is required both to keep traffic flowing and to eliminate biases from particular judges.
  1. If there is a line, the submitter must return to the back of the line upon completion of the three items.
  2. If there is no line, the submitter must move to a different judge to submit more items.
  3. Judges and Base Leedurs are entitled to further limit the number of items judged at once if needed, to decrease wait times.
', 'There will be Skule Patrollers and Base Leedurs at each station to promote safety and control traffic at each station.
  1. The Base Leedurs and Patrollers must be obeyed, if they get sad points will be deducted.
', @@ -105,7 +102,7 @@ export const rules = { }, { title: 'Prizes', - sub: 'The winners of the Havenger Scunt will receive a super cool first tier prize! The second place team will receive a super cool second tier prize! The third place group will receive a super cool third tier prize! All of these groups will earn the ability to go to other teams and say "Neener, neener, etc.", "HAHAHAHA HAHAHAHA! IN YOUR FACE #%$@*#*$*#!" or something similar. Essentially bragging rights forever.', + sub: 'The winners of the S!cavenger H!unt will receive a super cool first tier prize! The second place team will receive a super cool second tier prize! The third place group will receive a super cool third tier prize! All of these groups will earn the ability to go to other teams and say "Neener, neener, etc.", "HAHAHAHA HAHAHAHA! IN YOUR FACE #%$@*#*$*#!" or something similar. Essentially bragging rights forever.', items: [ 'Prizes will be available for pickup at Engineering Stores (located in the Pit) from Thursday, September 8th to Friday, September 16th, 2022.', @@ -115,7 +112,7 @@ export const rules = { }, { title: 'Kidnapping', - sub: 'Any kidnapping requested by judges that occurs during the Havenger Scunt must follow this code:', + sub: 'Any kidnapping requested by judges that occurs during the S!cavenger H!unt must follow this code:', items: [ 'In accordance with the second guiding principle the kidnapping should be well planned. Knowing in advance how the kidnapee will respond, or pre-staging the kidnapping is essential for avoiding conflict.', 'Any use of force must desist if the kidnapee is unwilling to participate.', @@ -128,10 +125,10 @@ export const rules = { ], }, { - title: 'Havenger Scunt Chairs', + title: 'S!cavenger H!unt Chairs', sub: 'Oh Hey, that’s us!', items: [ - 'Any and all disputes will be brought before the Havenger Scunt Chairs who are infallible - as all decisions are infallible, they are also final.', + 'Any and all disputes will be brought before the S!cavenger H!unt Chairs who are infallible - as all decisions are infallible, they are also final.', 'The Chairs have the reserved right to deduct up to infinity points from any team that leaves a mess in the completion of Scunt Items. Teams should thus clean up their messes to avoid the humiliation and shame that comes with being singled out for leaving a mess.', 'The Chairs have the reserved right to deduct up to infinity points from any team found to be in violation of Section 12 rules (Kidnapping) as laid out above or for breaking the law. This is only an option for situations that can be resolved to the satisfaction of all parties.', 'The Chairs have the reserved right to disqualify teams or individuals that are found to be in irreparable breach of these rules. Furthermore, it is the Chairs’ responsibilities to bar judges that have proven to be in breach of their expected conduct.', @@ -141,12 +138,12 @@ export const rules = { }, { title: 'Rules', - sub: 'These rules are up to the interpretation of the Havenger Scunt Chairs, and may be changed at any time.', + sub: 'These rules are up to the interpretation of the S!cavenger H!unt Chairs, and may be changed at any time.', }, { title: 'Liability', - sub: 'The University of Toronto, the Engineering Society, the Orientation Committee, and the Havenger Scunt executive committee will not be held accountable for illegal or unethical actions performed by event participants. The same parties will also not be liable for any injuries sustained through direct or indirect participation in the event.', + sub: 'The University of Toronto, the Engineering Society, the Orientation Committee, and the S!cavenger H!unt executive committee will not be held accountable for illegal or unethical actions performed by event participants. The same parties will also not be liable for any injuries sustained through direct or indirect participation in the event.', items: [], }, ], diff --git a/client/src/util/scunt-judges.jsx b/client/src/util/scunt-judges.jsx index 8a5f0cf4..a36f0230 100644 --- a/client/src/util/scunt-judges.jsx +++ b/client/src/util/scunt-judges.jsx @@ -1 +1,278 @@ -export const scuntJudges = []; +import erika from '../assets/judges/erika.jpg'; +import celin from '../assets/judges/celin.jpg'; +import ben from '../assets/judges/ben.jpg'; +import Kaija from '../assets/judges/kaija.jpeg'; +import alexi from '../assets/judges/alexi.jpg'; +import karen from '../assets/judges/karen.jpg'; +import nat from '../assets/judges/nat.jpg'; +import khalil from '../assets/judges/khalil.jpg'; +import tanya from '../assets/judges/tanya.jpg'; +import luka from '../assets/judges/luka.jpg'; +import novera from '../assets/judges/novera.jpg'; +import jeremy from '../assets/judges/jeremy.jpg'; +import rimjot from '../assets/judges/rimjot.jpg'; +import katie from '../assets/judges/katie.jpg'; +import emaan from '../assets/judges/emaan.jpg'; +import amelie from '../assets/judges/amelie.jpg'; +import tech from '../assets/judges/tech.png'; + +export const scuntJudges = [ + { + name: 'Tech Team', + description: 'Wink wink we made the website... we have unlimited bribe points...', + content: [ + 'Follow each of us on insta', + 'Star the website repo on GitHub', + 'Fix a bug on the website', + 'Coding takes energy. Energy comes from food. We like food. Enough said...', + 'Draw a nice pic of our team', + 'Appreciate the work we have given to Frosh week', + 'Have a nice convo with us :)', + ], + img: tech, + }, + { + name: 'Erika', + description: + "Waddup homies, I'm Erika (MECH 2T3 + PEY)! You can find me somewhere in the Pit- my home (15 mins) away from home <3. My favorite pasttimes include looking at pictures of otters holding hands, excessive crying, and curling up in balls until I become dirt.", + content: [ + 'A dog to pet (bonus points if it is a very very long dog, or in a hotdog costume)', + 'A smooch on the cheek from Mario Baker (bonus points for his hand in marriage)', + 'Make me a playlist', + 'An essay on why alcohol is bad and should NEVER be permitted at any and all university events, especially in the Pit (bonus points for funniness)', + 'Food of any sort', + 'Convince someone to get their jacket weened', + ], + img: erika, + }, + { + name: 'Celin', + description: + 'Heyo everyone, I"m Celin (Mech 2T5) and I commute all the way from Aurora (so sad). My toxic trait is that I make commuting my entire identity. I also love defying gravity temporarily, jumping, cats, and Skule.', + content: [ + 'Come up with a new engineering dance to an anime song and perform it', + 'Make/bring me an exotic meal under 10 dollars', + 'As many Ultimate F!rosh as you can find (past or present) doing an epic jump sequence (Bonus points for amount of UFs and creativity of jump sequence)', + 'A picture of your team with an old ttc streetcar', + 'The funniest patch you can find', + "Mr Blue and Gold's hardhat", + ], + img: celin, + }, + { + name: 'Ben', + description: + 'Hello hello I"m Ben (EngSci 2T4 + PEY)! I come from a distant rural community (KW) but I basically live in the Pit full time. I"m a big fan of truthful and accurate newspapers, as well as leafy greens! I can drive a tractor and I have (accidentally) tipped one (1) cow.', + content: [ + 'A DIY musical instrument', + 'One head of lettuce to share', + 'A drawing of me', + 'A better chair', + 'A cool rock', + 'A cool bug', + 'Blackout poetry with the Toike', + 'Something tasty', + 'A little kiss on the forehead from a SUDS manager', + ], + img: ben, + }, + { + name: 'Kaija', + description: + 'I"m Kaija and I am an EngSci (unfortunate ik) 2T5! I enjoy many normal hobbies like crocheting, singing and baking and I also enjoy even normaler hobbies like being in the pit for long periods of time, accidentally overcommitting and recreational screaming. Oh and I am from Alberta (yeehaw!) (feel free to use this against me) Uh I have bribes too, I promise', + content: [ + "Perform your favourite song for me and then explain to me why it's your favourite. (bonus points if I add it to my playlist!)", + 'Have the Lady Godiva Memorial Bnad serenade me', + 'Something I can add to my covvies (patches are good but creativity is encouraged!)', + 'Find a scunt chair (past or present) and do something nice for them (provide me with proof!)', + 'Teach me to wink with my left eye (points for effort because I am a lost cause)', + 'Make me cool new earrings', + 'Any number of bees', + ], + img: Kaija, + }, + { + name: 'Alexi', + description: + "Hello nerds!! I'm Alexi and an NΨ2T3 + PEY. Yes, the back pain has started along with fourth year, but it's fine!! I game sometimes, but my aim is so bad it actually takes skill to be as bad as me. If you can teach me to get better you'll have a special place in my heart.", + content: [ + "do 30 push-ups. If you do even one push-up with me on your back I'll give you bonus points.", + "Explain to me why when a ship transports something it's cargo but when a car transports something it's a shipment", + "Show that 9 = 10. Bonus points if you're an engineer about it", + 'Tell me why', + 'Make me laugh with your best dad joke', + 'Guess the longest distance I have ever driven in one stretch (including gas and bathroom breaks)', + "Beat me in a fair eating contest using a meal of your choice. I'll even pay you back if you win (I can't eat forever so this is a one time deal)", + ], + img: alexi, + }, + { + name: 'Karen', + description: + "Hello! My friends call me Karen and the Dean calls me trouble. I'm a ECE1T9+???, and I'm here for both a long time and also a good time. My hobbies include irrigation systems, wittowy hitting the gwiddy durwing fwosh week, and arson.", + content: [ + 'An original erotic fanfiction between Sudsman and the LGMBeaver', + "Sing for me, with guitar accompaniment, the 'Stuart Little's Not A Mouse' song by Jordan Keyes", + 'Food (must be tasty)', + 'Wear a full body denim joutfit, with minimum 5 different pieces', + 'A bottle of pickle ranch', + 'A John Denver CD', + 'patch???', + "Stella Gregorski's University Degree (folded)", + ], + img: karen, + }, + { + name: 'Nat', + description: + 'Hey party people! I"m Nat an MSE 2T4 + PEY (yes we are the material gorls). I don"t condone stealing from small local businesses, but big box corporations are free game (for legal reasons this is a joke). Ask me about my go-to vintage stores or about the time that I got lost in the city sewer system and I"d be happy to tell you!', + content: [ + 'Bring me an ultrasound of a farm animal', + 'Give a glam makeover to an engineering building', + 'A drag performer (bonus points if they perform)', + 'Make a creative disguise', + 'Some container of candy corn (bonus points if there is exactly 69 pieces inside)', + "Print and post my propaganda up around campus (bonus points if it's somewhere unexpected)", + 'A live bird (bonus points if it can talk)', + 'Something that I would find meaningful', + ], + img: nat, + }, + { + name: 'Khalil', + description: + "Hi everyone! My name's Khalil and I'm an EngSci 2T3 in the ECE option. I love computers (obviously) and have built one from part I found in the trash, live music, and video games. I just finished my PEY at intel (ik im old) and I'm also in UTAT space!", + content: [ + 'A Colins era CIV102 notebook', + "Mr B&G pants (Not the ones they're wearing please), or Lady Godiva horse", + 'Patches from another university (More points the further the uni is, or the weirder the patch is)', + 'A dog!!', + 'The smallest USB (storage-wise) you can find', + 'Old Comics', + 'Justify your favourite bubble tea', + 'Ikea Plushies', + ], + img: khalil, + }, + { + name: 'Tanya', + description: + 'Howdy! Im Tanya and an ECE 2T5, I am a fan of traveling to different countries, reading fanfics and wasting all my money on food!', + content: [ + 'bring me a live animal (extra points if its a farm animal)', + "a photo of a campus study spot I haven't been to", + 'make me a cool tattoo design', + "sing 'ole' MacDonald had a farm' in front of a mcdonalds", + 'make me a paper crown', + 'perform an animal-sound off with another scunt group (oink/bark/sheep sounds at other groups)', + 'sign one of the scunt-co-chairs body part in permeant marker', + ], + img: tanya, + }, + { + name: 'Luka', + description: + 'Hi All! I am Luka and I am a Eng Sci BME 2T3 + PEY. I am into every sport possible so I may or may not have a soft spot for sports related bribes . Other than that, I love to travel, make bad jokes, and watch sitcoms. I am also involved with UT BIOME so come talk to me if you want to learn more about biomedical design teams! ', + content: [ + 'Paint/Draw a portrait of me (needs to pass my approval) 🖼️', + 'Bring me anything purple not from your frosh kit 💜', + 'Perform the final scene of Jack and Rose in the Titanic (extra for singing “My Heart Will Go On” by Celine Dion) 🚢', + 'Bring me a hard copy of Stewart Calculus 📕', + 'Food is the way to my heart ❤️', + 'Wear some Toronto Maple Leafs gear 🍁', + 'Bring me some dog toys (bonus points if you wear a dog collar and leash while doing it)', + ], + img: luka, + }, + { + name: 'Novera', + description: + "Hiya frens, I'm Novera, an Engsci (fiziks) 2T5. If I'm not taking photos around Skule or being overcommitted to Engsoc and Design Teams, then you'll probably find me eeping through 9 am lectures, being a competitive vroom vroom gamer grill, or religiously organizing my monthly Spotify playlists.", + content: [ + 'A cat to pet and give cuddles to', + 'Signed and addressed love letter to me from anyone in Engsoc VP team (Past or Present)', + '3D CAD design me something cool', + "Live karaoke performance with backup dancers (Bonus points if you've got the fit or its one of my favourite artists)", + 'Let me talk to ur mum on the phone', + 'Print out your favorite picture of me holding a camera on photos.skule.ca and sign it', + 'Make me a DIY friendship bracelet', + 'Get me a list of people that would actually date Emaan and let me filter through it (Potentials must be upper year only)', + ], + img: novera, + }, + { + name: 'Jeremy', + description: + "Hi peeps, my name is Jeremy and I am a mech 2T3+PEY from the the good ol' USA (Seattle). If I am not busy trying to figure out how to do skule, I can usually be found on the volleyball court or at some UTAT event. Below is the list of bribes I have.", + content: [ + 'The best, leveled up, instant ramen (quality over quantity)', + 'Complete my sad patch collection (bonus points if it is old and relates to one I already have)', + 'The OG, better version of the CN Tower', + 'Come up with a nickname/pun using my name that I have not heard already', + 'Something from my favorite basketball player (hint: we have something in common)', + 'Teach me how to properly do a volleyball dolphin dive (bonus points if it is with a volleyball)', + 'A list of UTAT Executive directors past and present and the years they served', + ], + img: jeremy, + }, + { + name: 'Rimjot', + description: + "Howdy y'all! My name's Rimjot and I'm a CHEM 2T5. You'll likely spot me around a library trying to study for something or at an event with free food (we love free food)! But otherwise I really enjoy listening to music (Spotify increasing its monthly fee made me cry) and walking weirdly fast until I realize I'm walking super fast and then slowing down because suddenly I'm tired.", + content: [ + "Make me something containing flowers (bonus points if you're able to incorporate my favourite colour) (no I'm not telling you what my favourite colour is)", + "A patch to add to my collection pls (bonus points if it's not a UofT patch)", + 'Make me a little playlist', + "A picture of something that you'd find on a farm that's actually in a big city (bonus points if it's not located in a store)", + 'Find my favourite study spot', + 'Tell a Scunt Chair I said hi in an unconventional way (pls provide proof)', + ], + img: rimjot, + }, + { + name: 'Katie', + description: + "Heyyy I'm Katie. I'm an EngSci 2T5 in the Biomedical Systems Engineering option. I am literally from a town that used to be called Farmersville so Frosh this year is my thing. I can also totally be bought so please bribe me.", + content: [ + 'Sing Taylor Swift (bonus if you do All Too Well 10 minute version)', + 'Figure out my favourite night-before-a-midterm food and get it for me', + "Draw me a picture that would look good in my apartment (I'm in desperate need of artwork)", + 'Find me a patch you think would look fire on my overalls', + 'Get me a book you think I need to read', + 'DIY me something to add to my outfit', + 'Write me a poem and perform it (more drama, more points)', + ], + img: katie, + }, + { + name: 'Emaan', + description: + "Heyo cuties, I'm Emaan, an EngSci 2T5, choosing to go into the Energy Systems option after pouring my heart and soul into making it everybody else's problem because my indecisive ass has issues. For entertainment purposes, you can probably find my face stuck behind a phone documenting your life for the sole reason of subscribing you to FarmersOnly because I believe everybody deserves love! I'm a dramatic piece of shit, but also a pathological people pleaser so you can probably beg me for points but here's some potential bribes since I'm assuming (unlike me) you probably want to keep your dignity intact:", + content: [ + 'guess articles I wrote in the Toike (bonus points if you can get me to actually admit it)', + "get me a customized Iced Capp from Tims to try (note: no whipped cream, no alcohol, no FOOD in it pls i'll cry and you'll get negative points, and make sure it's under $5)", + 'get Mario to design me personalized converse', + 'for educational purposes, DM me a detailed explanation of what a red flag is (pls I need to know)', + 'get/make me fake flowers', + "love letters from people in the F!rosh Week 2T3 Marketing team (bonus points if it's from Novera)", + 'make me cool rings! (bonus points if you can get my ring size right)', + "make a tiktok/take a bereal with me because I'm into clout", + ], + img: emaan, + }, + { + name: 'Amélie', + description: + 'Hi hi I"m Amélie I"m a Mech 2T4 + PEY. l have two cats back home in Chicago named Saffron and Edward Geraldson the 3rd and I like launching things into the sky and zooming down hills', + content: [ + 'Build me a model of a rocket-propelled toboggan', + 'Put together a frosh kit for me with things around the pit', + 'Perform a mashup of the English, American, and Canadian National anthem', + 'Handstand', + 'Design a patch for me and explain the reasoning behind your design', + "Bring me the picture of my girlfriend in the varsity (I'll tell you the edition for a cookie)", + 'Haiku on why I should not go into work tomorrow', + ], + img: amelie, + }, +]; diff --git a/client/src/util/sponsors.jsx b/client/src/util/sponsors.jsx index c063ad39..d5ab2e23 100644 --- a/client/src/util/sponsors.jsx +++ b/client/src/util/sponsors.jsx @@ -1 +1,65 @@ -export const sponsors = []; +import Alumni from '../assets/sponsors/Alumni.jpg'; +import Neo from '../assets/sponsors/Neo.jpg'; +import Coco from '../assets/sponsors/Coco.jpg'; +import OSPE from '../assets/sponsors/OSPE.jpg'; +import PEO from '../assets/sponsors/PEO.png'; +import UTSU from '../assets/sponsors/UTSU.jpg'; +import Mogu from '../assets/sponsors/MoguMogu.png'; +import Nani from '../assets/sponsors/Nanis.png'; + +export const sponsors = [ + { + website: 'https://alumni.engineering.utoronto.ca/engineering-alumni-network/', + image: Alumni, // the sponsor image displayed on homepage (from "./client/src/assets/sponsors") + scale: 0.82, // can be used to display each image at a different size + rank: 'diamond', // rank of sponsor, can be used to display border + label: 'Diamond sponsor: Alumni Office', // the label when user hovers on image in 'View All' state + }, + { + website: 'https://www.neomaterials.com/', + image: Neo, + scale: 0.7, + rank: 'gold', + label: 'Gold sponsor: Neo Performance', + }, + { + website: 'https://www.cocofreshtea.ca/', + image: Coco, + scale: 0.7, + rank: 'gold', + label: 'Silver sponsor: Coco', + }, + { + website: 'https://www.utsu.ca/', + image: UTSU, + scale: 0.7, + rank: 'bronze', + label: 'Bronze sponsor: UTSU', + }, + { + website: 'https://www.peo.on.ca/', + image: PEO, + scale: 0.82, + rank: 'bronze', + label: 'Bronze sponsor: PEO', + }, + { + website: 'https://ospe.on.ca/', + image: OSPE, + scale: 0.82, + rank: 'bronze', + label: 'Bronze sponsor: OSPE', + }, + { + image: Mogu, + scale: 0.82, + rank: 'bronze', + label: 'Bronze sponsor: Mogu', + }, + { + image: Nani, + scale: 0.82, + rank: 'bronze', + label: 'Bronze sponsor: Nani’s Gelato', + }, +]; diff --git a/client/vite.config.js b/client/vite.config.js index fc3240f4..d536cce0 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -1,6 +1,16 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import pluginRewriteAll from 'vite-plugin-rewrite-all'; +import { dependencies } from './package.json'; + +function renderChunks(deps) { + let chunks = {}; + Object.keys(deps).forEach((key) => { + if (['react', 'react-router-dom', 'react-dom', '@react-pdf/renderer'].includes(key)) return; + chunks[key] = [key]; + }); + return chunks; +} // https://vitejs.dev/config/ export default defineConfig({ @@ -14,5 +24,13 @@ export default defineConfig({ }, build: { sourcemap: true, + rollupOptions: { + output: { + manualChunks: { + vendor: ['react', 'react-router-dom', 'react-dom'], + ...renderChunks(dependencies), + }, + }, + }, }, }); diff --git a/deploy/go.mod b/deploy/go.mod deleted file mode 100644 index 84b5ed55..00000000 --- a/deploy/go.mod +++ /dev/null @@ -1,15 +0,0 @@ -module main - -go 1.18 - -require ( - github.com/digitalocean/godo v1.80.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-querystring v1.1.0 // indirect - github.com/sethvargo/go-envconfig v0.6.0 // indirect - github.com/sethvargo/go-githubactions v1.0.0 // indirect - golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect - golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.0 // indirect -) diff --git a/deploy/go.sum b/deploy/go.sum deleted file mode 100644 index 048884f8..00000000 --- a/deploy/go.sum +++ /dev/null @@ -1,382 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/digitalocean/godo v1.80.0 h1:ZULJ/fWDM97YtO7Fa+K6hzJLd7+smCu4N+0n+B/xtj4= -github.com/digitalocean/godo v1.80.0/go.mod h1:BPCqvwbjbGqxuUnIKB4EvS/AX7IDnNmt5fwvIkWo+ew= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/sethvargo/go-envconfig v0.6.0 h1:GxxdoeiNpWgGiVEphNFNObgMYRN/ZvI2dN7rBwadyss= -github.com/sethvargo/go-envconfig v0.6.0/go.mod h1:00S1FAhRUuTNJazWBWcJGvEHOM+NO6DhoRMAOX7FY5o= -github.com/sethvargo/go-githubactions v1.0.0 h1:5mYGPNxIwIXaS8MLj4uYGWM8QM8giUVqA4FuSYOZjXE= -github.com/sethvargo/go-githubactions v1.0.0/go.mod h1:UaidDD1ENTLXzTtj/4MnYjY40/5WLijgn2O8KBsdv7o= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5 h1:bRb386wvrE+oBNdF1d/Xh9mQrfQ4ecYhW5qJ5GvTGT4= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/deploy/main.go b/deploy/main.go deleted file mode 100644 index b158aa4d..00000000 --- a/deploy/main.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "context" - "fmt" - "github.com/digitalocean/godo" - "os" - "time" -) - -func main() { - client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_API_KEY")) - userData := os.Getenv("USER_DATA") - region := os.Getenv("REGION") - name := os.Getenv("NAME") - ip := os.Getenv("IP") - tag := os.Getenv("TAG") - - //dropletName := "first-test-droplet" - - opt := &godo.ListOptions{} - - ctx := context.Background() - - droplets, _, err := client.Droplets.ListByTag(ctx, tag, opt) - - createRequest := &godo.DropletCreateRequest{ - Name: name, - Region: region, - Size: "s-1vcpu-1gb", - Image: godo.DropletCreateImage{ - Slug: "docker-20-04", - }, - UserData: userData, - Tags: []string{tag}, - } - - newDroplet, _, err := client.Droplets.Create(ctx, createRequest) - - if err != nil { - fmt.Printf("Something bad happened: %s\n\n", err) - } - fmt.Printf("New droplet created!\nName: %s\nCreated at: %s\nStatus: %s\n", newDroplet.Name, newDroplet.Created, newDroplet.Status) - - dropletId := newDroplet.ID - for { - newDroplet, _, err = client.Droplets.Get(ctx, dropletId) - if newDroplet.Status == "active" { - fmt.Printf("Droplet is active!\n") - break - } else { - fmt.Printf("Client has status: %s\n", newDroplet.Status) - time.Sleep(15 * time.Second) - } - } - - _, _, err = client.FloatingIPActions.Assign(ctx, ip, newDroplet.ID) - - if err != nil { - fmt.Printf("There was an error assigning the floating IP to the new droplet: %s", err) - } - - if len(droplets) > 0 { - _, err = client.Droplets.Delete(ctx, droplets[0].ID) - - if err != nil { - fmt.Printf("There was an error deleting the droplet: %s", err) - } - } -} diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 00000000..966f6553 --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,23 @@ +version: '3.8' + +services: + mongodb-test: + image: mongo + container_name: mongo-test + restart: unless-stopped + environment: + - MONGO_INITDB_ROOT_USERNAME=admin + - MONGO_INITDB_ROOT_PASSWORD=root + - MONGO_INITDB_DATABASE=testingDatabase + ports: + - "27017:27017" + + redis-test: + image: redis + container_name: redis-test + restart: unless-stopped + ports: + - "7001:7001" + environment: + - REDIS_PORT_NUMBER=7001 + - REDIS_PASSWORD=root \ No newline at end of file diff --git a/package.json b/package.json index 86300e38..613fa7eb 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test:api": "cd server && yarn test", "start:dev": "concurrently \"cd server && yarn start:dev\" \"cd client && yarn dev\"", "install:all": "concurrently \"cd server && yarn install\" \"cd client && yarn install\"", "prepare": "husky install" @@ -14,13 +14,10 @@ "license": "ISC", "devDependencies": { "husky": "^8.0.0", - "lint-staged": "^12.4.1" + "lint-staged": "^13.2.3" }, "dependencies": { - "concurrently": "^7.1.0", - "react-full-screen": "^1.1.1", - "react-lazy-load-image-component": "^1.5.5", - "react-lazyload": "^3.2.0", - "socket.io-client": "^4.5.2" + "concurrently": "^8.2.0", + "socket.io-client": "^4.5.2" } } diff --git a/server/.eslintrc.js b/server/.eslintrc.js index a79e09d0..3fc8c580 100644 --- a/server/.eslintrc.js +++ b/server/.eslintrc.js @@ -1,15 +1,13 @@ module.exports = { - plugins: ['jest'], extends: ['eslint:recommended', 'plugin:prettier/recommended'], env: { es6: true, node: true, - jest: true, }, + parser: '@babel/eslint-parser', parserOptions: { ecmaVersion: 2020, }, - parser: '@babel/eslint-parser', rules: { 'prettier/prettier': [ 'error', @@ -22,7 +20,7 @@ module.exports = { 'no-multiple-empty-lines': ['error'], 'no-new-symbol': ['error'], 'no-trailing-spaces': ['error'], - 'no-undef': ['warn'], + 'no-undef': ['error'], 'no-unused-vars': ['error', { argsIgnorePattern: 'next' }], 'object-curly-spacing': ['error', 'always'], 'object-shorthand': ['error'], diff --git a/server/.gitignore b/server/.gitignore index ee16c002..3c66281f 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -25,3 +25,5 @@ dist-ssr # Env file .env +.nyc_output +coverage \ No newline at end of file diff --git a/server/.nycrc.json b/server/.nycrc.json new file mode 100644 index 00000000..532d7d4d --- /dev/null +++ b/server/.nycrc.json @@ -0,0 +1,15 @@ +{ + "all": true, + "include": [ + "src/models/*.js", + "src/services/*.js" + ], + "exclude": [ + "src/services/EmailServices.js", + "src/services/passport.js" + ], + "check-coverage": true, + "branches": 80, + "lines": 80, + "statements": 80 +} \ No newline at end of file diff --git a/server/.prettierignore b/server/.prettierignore index 3c3629e6..1d027766 100644 --- a/server/.prettierignore +++ b/server/.prettierignore @@ -1 +1,59 @@ node_modules +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local +*/backendlogs.txt +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Env file +.env + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Env file +.env + +# Database stuff +mongo-volume diff --git a/server/Dockerfile b/server/Dockerfile index 34026336..59e4c04c 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,6 +1,7 @@ FROM node:18-alpine WORKDIR /app COPY package.json yarn.lock ./ + RUN yarn install COPY ./ ./ CMD ["yarn", "start:dev"] diff --git a/server/jest.config.js b/server/jest.config.js deleted file mode 100644 index 4553c110..00000000 --- a/server/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = {}; - -process.env = Object.assign(process.env, { - MODE: 'test', -}); diff --git a/server/package.json b/server/package.json index 2297bd3f..f55e521e 100644 --- a/server/package.json +++ b/server/package.json @@ -6,7 +6,9 @@ "scripts": { "format": "prettier --write \"**/*.+(js|json)\"", "lint": "eslint src", - "test": "jest --runInBand", + "test": "nyc --reporter=lcov --reporter=text mocha --recursive --exit", + "testing": "nodemon -x nyc --reporter=lcov --reporter=text mocha --recursive --exit", + "test:actions": "nyc --reporter=text-summary mocha --recursive --exit", "start:dev": "set NODE_ENV=development && nodemon -L src/server.js", "start": "set NODE_ENV=production && node src/server.js" }, @@ -17,43 +19,42 @@ "author": "", "license": "ISC", "devDependencies": { - "@babel/core": "^7.17.10", - "@babel/eslint-parser": "^7.17.0", + "@babel/core": "^7.22.9", + "@babel/eslint-parser": "^7.22.9", "@babel/plugin-proposal-optional-chaining": "^7.16.7", - "eslint": "^8.15.0", + "eslint": "^8.45.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-jest": "^26.2.2", - "eslint-plugin-prettier": "^4.0.0", - "jest": "^28.1.0", "lint-staged": "^13.0.0", - "mongodb-memory-server": "^8.6.0", - "nodemon": "^2.0.16", - "prettier": "^2.6.2", - "supertest": "^6.2.3" + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "eslint-plugin-prettier": "^5.0.0", + "nodemon": "^3.0.1", + "prettier": "^3.0.0" }, "dependencies": { "@aws-sdk/client-sesv2": "^3.100.0", "bcrypt": "^5.0.1", "body-parser": "^1.20.0", "bull": "^4.8.3", - "connect-mongo": "^4.6.0", + "connect-mongo": "^5.0.0", "cors": "^2.8.5", "email-validator": "^2.0.4", "express": "^4.18.1", "express-session": "^1.17.3", - "jsonwebtoken": "^8.5.1", + "jsonwebtoken": "^9.0.1", "mime": "^3.0.0", "mimemessage": "^1.0.5", - "mongoose": "^6.3.3", + "mongodb": "^5.7.0", + "mongoose": "^7.4.0", "multer": "^1.4.5-lts.1", "passport": "^0.6.0", "passport-local": "^1.0.0", "pino": "^8.14.1", "pino-http": "^8.3.3", - "react-full-screen": "^1.1.1", "socket.io": "^4.5.1", "socket.io-client": "^4.5.2", - "stripe": "^9.9.0", + "stripe": "^9.9.0", "swagger-jsdoc": "^6.2.1", "swagger-ui-express": "^4.4.0" } diff --git a/server/src/controllers/AnnouncementController.js b/server/src/controllers/AnnouncementController.js index be5ffe67..823b5783 100644 --- a/server/src/controllers/AnnouncementController.js +++ b/server/src/controllers/AnnouncementController.js @@ -3,7 +3,7 @@ const AnnouncementServices = require('../services/AnnouncementServices'); const AnnouncementController = { async getAnnouncement(req, res, next) { try { - const allAnnouncements = await AnnouncementServices.getAllAnnouncements(); + const allAnnouncements = await AnnouncementServices.getAll(); return res.status(200).send({ announcements: allAnnouncements }); } catch (e) { req.log.fatal({ msg: 'Unable to get announcement', e }); @@ -14,9 +14,7 @@ const AnnouncementController = { async getCompletedAnnouncements(req, res, next) { const currentUser = req.user; try { - const completedAnnouncements = await AnnouncementServices.getCompletedAnnouncements( - currentUser, - ); + const completedAnnouncements = await AnnouncementServices.getCompleted(currentUser); return res.status(200).send({ announcements: completedAnnouncements }); } catch (e) { req.log.fatal({ @@ -32,7 +30,7 @@ const AnnouncementController = { const currentUser = req.user; const announcementId = req.params.id; try { - const completedAnnouncements = await AnnouncementServices.completeAnnouncementElement( + const completedAnnouncements = await AnnouncementServices.complete( announcementId, currentUser, ); @@ -53,7 +51,7 @@ const AnnouncementController = { const id = req.params.id; try { - await AnnouncementServices.updateAnnouncementElement(id, data); + await AnnouncementServices.update(id, data); return res.status(200).send({ message: 'Successfully updated announcement element!' }); } catch (e) { req.log.fatal({ msg: 'Unable to update announcement element', e }); @@ -65,7 +63,7 @@ const AnnouncementController = { const data = req.body.announcementData; try { - await AnnouncementServices.saveNewAnnouncementElement(data); + await AnnouncementServices.create(data); return res.status(200).send({ message: 'Successfully added announcement element!' }); } catch (e) { req.log.fatal({ msg: 'Unable to create announcement', e }); @@ -77,7 +75,7 @@ const AnnouncementController = { const id = req.params.id; try { - await AnnouncementServices.deleteAnnouncementElement(id); + await AnnouncementServices.delete(id); return res.status(200).send({ message: 'Successfully deleted announcement element!' }); } catch (e) { req.log.fatal({ msg: 'Unable to delete announcement', e }); diff --git a/server/src/controllers/FaqController.js b/server/src/controllers/FaqController.js index 7820f8b4..9c5e07ee 100644 --- a/server/src/controllers/FaqController.js +++ b/server/src/controllers/FaqController.js @@ -11,7 +11,7 @@ const FaqController = { */ async getAnsweredFaqList(req, res, next) { try { - const answeredQuestions = await FaqServices.getAnsweredQuestions(); + const answeredQuestions = await FaqServices.getAnswered(); res.status(200).send({ faqs: answeredQuestions }); } catch (err) { req.log.fatal({ msg: 'Unable to get answered FAQ questions', err }); @@ -29,7 +29,7 @@ const FaqController = { */ async getUnansweredFaqList(req, res, next) { try { - const unansweredQuestions = await FaqServices.getUnansweredQuestions(); + const unansweredQuestions = await FaqServices.getUnanswered(); res.status(200).send({ faqs: unansweredQuestions }); } catch (err) { req.log.fatal({ msg: 'Unable to get unanswered FAQ questions', err }); @@ -47,7 +47,7 @@ const FaqController = { */ async getAllFaqList(req, res, next) { try { - const allQuestions = await FaqServices.getAllQuestions(); + const allQuestions = await FaqServices.getAll(); res.status(200).send({ faqs: allQuestions }); } catch (err) { req.log.fatal({ msg: 'Unable to get all FAQ questions', err }); @@ -67,7 +67,7 @@ const FaqController = { try { const { email, question, category } = req.body; // Don't allow frosh to post an answer - set it to undefined - const newFaq = await FaqServices.createNewQuestion(email, question, undefined, category); + const newFaq = await FaqServices.create(email, question, undefined, category); res.status(200).send(newFaq.toObject()); } catch (err) { req.log.fatal({ msg: 'Unable to create FAQ question', err }); @@ -86,7 +86,7 @@ const FaqController = { async createQuestionWithAns(req, res, next) { try { const { email, question, answer, category } = req.body; - const newFaq = await FaqServices.createNewQuestion(email, question, answer, category); + const newFaq = await FaqServices.create(email, question, answer, category); res.status(200).send(newFaq.toObject()); } catch (err) { req.log.fatal({ msg: 'Unable to create FAQ question with answer', err }); @@ -105,7 +105,7 @@ const FaqController = { async deleteQuestion(req, res, next) { try { const { faqId } = req.params; - await FaqServices.deleteQuestion(faqId); + await FaqServices.delete(faqId); res.status(200).send({ message: 'Successfully deleted FAQ!', deletedId: faqId }); } catch (err) { req.log.fatal({ msg: 'Unable to delete FAQ question', err }); @@ -126,7 +126,7 @@ const FaqController = { const { faqId } = req.params; const update = req.body; update.isAnswered = update.answer ? true : false; - const updatedFaq = await FaqServices.updateQuestion(faqId, update); + const updatedFaq = await FaqServices.update(faqId, update); res.status(200).send(updatedFaq.toObject()); } catch (err) { req.log.fatal({ msg: 'Unable to update FAQ question', err }); diff --git a/server/src/controllers/FroshController.js b/server/src/controllers/FroshController.js index 6868cfb5..53a9c1eb 100644 --- a/server/src/controllers/FroshController.js +++ b/server/src/controllers/FroshController.js @@ -12,7 +12,6 @@ const FroshController = { */ async registerFrosh(req, res, next) { console.log('Start frosh registration'); - try { const user = req.user; const registrationInfo = req.body; @@ -23,6 +22,7 @@ const FroshController = { registrationInfo.froshGroup = froshGroup; registrationInfo.froshGroupIcon = froshGroupIcon; const { url, payment_intent } = await PaymentServices.createCheckoutSession(user.email); + const frosh = ( await FroshServices.upgradeToFrosh(user, registrationInfo, payment_intent) ).getResponseObject(); @@ -39,6 +39,7 @@ const FroshController = { res.status(200).send({ url }); } } catch (e) { + console.log(e); req.log.fatal({ msg: 'Unable to register Frosh: user ' + req.user.id, e, diff --git a/server/src/controllers/PaymentController.js b/server/src/controllers/PaymentController.js index f505ff59..661111db 100644 --- a/server/src/controllers/PaymentController.js +++ b/server/src/controllers/PaymentController.js @@ -7,8 +7,8 @@ const PaymentController = { const signature = req.headers['stripe-signature']; try { event = await PaymentServices.decodeWebhookEvent(req.body, signature); - } catch (err) { - next(new Error('UNAUTHORIZED')); + } catch (error) { + next(error); } try { switch (event.type) { @@ -29,9 +29,9 @@ const PaymentController = { console.log(`Unhandled event type: ${event.type}`); } res.status(200).send({ message: 'Webhook processed' }); - } catch (err) { - req.log.fatal({ msg: 'Unable to process payment', err }); - next(err); + } catch (error) { + req.log.fatal({ msg: 'Unable to process payment', error }); + next(error); } }, diff --git a/server/src/controllers/QrController.js b/server/src/controllers/QrController.js index 714ed5a8..1969c9bb 100644 --- a/server/src/controllers/QrController.js +++ b/server/src/controllers/QrController.js @@ -31,20 +31,20 @@ const QrController = { const { userID, date, tzOffset } = req.body; const day = new Date(Date.parse(date) - tzOffset * 60 * 1000); try { - const frosh = ( - await FroshServices.getFilteredFroshInfo( - { _id: userID }, - { - firstName: 1, - lastName: 1, - preferredName: 1, - pronouns: 1, - email: 1, - preKit: 1, - signInDate: 1, - }, - ) - )[0]; + const [frosh] = await FroshServices.getFilteredFroshInfo( + { _id: userID, isRegistered: true }, + { + firstName: 1, + lastName: 1, + preferredName: 1, + pronouns: 1, + email: 1, + preKit: 1, + signInDate: 1, + shirtSize: 1, + photograph: 1, + }, + ); if (frosh.signInDate) { return res.status(200).send({ message: 'Frosh already marked as present', frosh }); @@ -66,7 +66,7 @@ const QrController = { try { const frosh = ( await FroshServices.getFilteredFroshInfo( - { _id: userID }, + { _id: userID, isRegistered: true }, { firstName: 1, lastName: 1, @@ -91,6 +91,39 @@ const QrController = { next(error); } }, + + async getFood(req, res, next) { + const { userID } = req.body; + + try { + const [frosh] = await FroshServices.getFilteredFroshInfo( + { _id: userID }, + { + firstName: 1, + lastName: 1, + preferredName: 1, + pronouns: 1, + medicalInfo: 1, + specficMedicalInfo: 1, + allergies: 1, + allergiesOther: 1, + gotFood: 1, + }, + ); + + if (frosh.gotFood) { + return res.status(200).send({ message: 'Food already picked up', frosh }); + } + + await FroshServices.updateFroshInfo(userID, { + gotFood: true, + }); + + return res.status(200).send({ message: 'Food picked up', frosh }); + } catch (error) { + next(error); + } + }, }; module.exports = QrController; diff --git a/server/src/controllers/ScuntGameSettingsController.js b/server/src/controllers/ScuntGameSettingsController.js index bbac6f85..f284ab1a 100644 --- a/server/src/controllers/ScuntGameSettingsController.js +++ b/server/src/controllers/ScuntGameSettingsController.js @@ -6,7 +6,7 @@ const ScuntGameSettingsController = { const gameSettings = await ScuntGameSettingsServices.getGameSettings(); return res.status(200).send({ message: 'Found game settings', - settings: gameSettings.map((u) => u.getResponseObject()), + settings: gameSettings, }); } catch (e) { req.log.fatal({ msg: 'Unable to retrieve scunt game settings', e }); @@ -46,7 +46,7 @@ const ScuntGameSettingsController = { ); return res.status(200).send({ message: 'Successfully updated Scunt game settings', - settings: [newSettings], + settings: newSettings, }); } catch (e) { req.log.fatal({ msg: 'Unable to update scunt game settings', e }); diff --git a/server/src/controllers/ScuntMissionController.js b/server/src/controllers/ScuntMissionController.js index 328d6c42..4342dac9 100644 --- a/server/src/controllers/ScuntMissionController.js +++ b/server/src/controllers/ScuntMissionController.js @@ -25,14 +25,7 @@ const ScuntMissionController = { isHidden = false, isJudgingStation = false, } = req.body; - await ScuntMissionServices.createMission( - number, - name, - category, - points, - isHidden, - isJudgingStation, - ); + await ScuntMissionServices.create(number, name, category, points, isHidden, isJudgingStation); return res.status(200).send({ message: 'Successfully created mission #' + number.toString() + ' - ' + name.toString(), }); @@ -48,7 +41,7 @@ const ScuntMissionController = { await ScuntMissionServices.deleteMission(id); return res.status(200).send({ message: `Successfully deleted mission: ${id}` }); } catch (e) { - req.log.fatal({ msg: 'Unable to delete scunt mission ' + id, e }); + req.log.fatal({ msg: 'Unable to delete scunt mission ' + req.params.id, e }); next(e); } }, diff --git a/server/src/controllers/ScuntTeamController.js b/server/src/controllers/ScuntTeamController.js index bfaf8fd4..a03372fe 100644 --- a/server/src/controllers/ScuntTeamController.js +++ b/server/src/controllers/ScuntTeamController.js @@ -22,8 +22,8 @@ const ScuntTeamController = { }, async getTeamPoints(req, res, next) { try { - const teamPoints = await ScuntTeamServices.getTeamPoints(); - return res.status(200).send({ message: 'Team points', teamPoints }); + const scuntTeams = await ScuntTeamServices.getTeamPoints(); + return res.status(200).send({ message: 'Team points', scuntTeams }); } catch (e) { req.log.fatal({ msg: 'Unable to get team points', e }); next(e); @@ -33,7 +33,11 @@ const ScuntTeamController = { try { const { teamNumber, points } = req.body; // const userId = req.user.id; - const { leadur } = await ScuntTeamServices.bribeTransaction(teamNumber, points, req.user); + const { scuntTeam, leadur } = await ScuntTeamServices.bribeTransaction( + teamNumber, + points, + req.user, + ); return res.status(200).send({ message: 'Successfully added bribe points for team #' + @@ -41,6 +45,7 @@ const ScuntTeamController = { ' of ' + points.toString(), user: leadur, + scuntTeam, }); } catch (e) { req.log.fatal({ msg: 'Unable to process bribe transaction', e }); @@ -51,7 +56,7 @@ const ScuntTeamController = { async getScuntJudges(req, res, next) { try { const judgeUsers = await ScuntTeamServices.getScuntJudges(); - return res.status(200).send({ message: 'Successfuly found judge users', users: judgeUsers }); + return res.status(200).send({ message: 'Successfuly found judge users', judges: judgeUsers }); } catch (e) { req.log.fatal({ msg: 'Unable to get scunt judges', e }); next(e); @@ -62,8 +67,10 @@ const ScuntTeamController = { try { const { judgeUserId, points, isAddPoints = false } = req.body; await ScuntTeamServices.refillBribePoints(judgeUserId, points, isAddPoints); + const judges = await ScuntTeamServices.getScuntJudges(); return res.status(200).send({ message: (isAddPoints ? 'Added ' : 'Set ') + points?.toString() + ' bribe points', + judges, }); } catch (e) { req.log.fatal({ msg: 'Unable to refill bribe points', e }); @@ -75,8 +82,10 @@ const ScuntTeamController = { try { const { teamNumber, missionNumber, points } = req.body; const result = await ScuntTeamServices.addTransaction(teamNumber, missionNumber, points); + const scuntTeams = await ScuntTeamServices.getTeamPoints(); return res.status(200).send({ message: result, + scuntTeams, }); } catch (e) { req.log.fatal({ msg: 'Unable to add scunt team transaction', e }); @@ -87,12 +96,14 @@ const ScuntTeamController = { try { const { teamNumber, points } = req.body; await ScuntTeamServices.subtractTransaction(teamNumber, points); + const scuntTeams = await ScuntTeamServices.getTeamPoints(); return res.status(200).send({ message: 'Successfully subtracted ' + points.toString() + ' points for team ' + teamNumber.toString(), + scuntTeams, }); } catch (e) { req.log.fatal({ msg: 'Unable to subtract scunt team transaction', e }); @@ -133,8 +144,11 @@ const ScuntTeamController = { async intializeTeams(req, res, next) { try { - const createdTeams = await ScuntTeamServices.initializeTeams(); - res.status(200).send({ message: `Successfully created ${createdTeams.length} teams!` }); + await ScuntTeamServices.initializeTeams(); + const scuntTeams = await ScuntTeamServices.getTeams(); + res + .status(200) + .send({ scuntTeams, message: `Successfully created ${scuntTeams.length} teams!` }); } catch (e) { req.log.fatal({ msg: 'Unable to initialize scunt teams', e }); next(e); @@ -155,11 +169,12 @@ const ScuntTeamController = { async renameScuntTeams(req, res, next) { const teamObjs = req.body.teamObjs; try { - teamObjs.map( - async (teamObj, index) => - await ScuntTeamServices.setTeamName(teamObjs[index]['number'], teamObjs[index]['name']), + const scuntTeams = await Promise.all( + teamObjs.map( + async (teamObj) => await ScuntTeamServices.setTeamName(teamObj.number, teamObj.name), + ), ); - res.status(200).send({ message: `Successfully renamed scunt teams!` }); + res.status(200).send({ message: `Successfully renamed scunt teams!`, scuntTeams }); } catch (e) { req.log.error({ msg: 'Unable to rename scunt teams', e }); next(e); diff --git a/server/src/controllers/TimelineController.js b/server/src/controllers/TimelineController.js index 6220a31f..8e5e0a7c 100644 --- a/server/src/controllers/TimelineController.js +++ b/server/src/controllers/TimelineController.js @@ -3,7 +3,7 @@ const TimelineServices = require('../services/TimelineServices'); const TimelineController = { async getTimeline(req, res, next) { try { - const allTimelines = await TimelineServices.getAllTimelines(); + const allTimelines = await TimelineServices.getAll(); return res.status(200).send({ timelines: allTimelines }); } catch (e) { req.log.error({ msg: 'Unable to get timeline', e }); @@ -15,14 +15,7 @@ const TimelineController = { const { date, eventName, description, link, linkLabel } = req.body; const { id } = req.params; try { - await TimelineServices.updateTimelineElement( - id, - date, - eventName, - description, - link, - linkLabel, - ); + await TimelineServices.update(id, date, eventName, description, link, linkLabel); return res.status(200).send({ message: 'Successfully updated Timeline element!' }); } catch (e) { req.log.fatal({ msg: 'Unable to update timeline event', e }); @@ -33,7 +26,7 @@ const TimelineController = { async createTimelineElement(req, res, next) { const { date, eventName, description, link, linkLabel } = req.body; try { - await TimelineServices.saveNewTimelineElement(date, eventName, description, link, linkLabel); + await TimelineServices.create(date, eventName, description, link, linkLabel); return res.status(200).send({ message: 'Successfully added Timeline element!' }); } catch (e) { req.log.fatal({ msg: 'Unable to create timeline event', e }); diff --git a/server/src/controllers/UserController.js b/server/src/controllers/UserController.js index 8c979fa9..a4ebaac4 100644 --- a/server/src/controllers/UserController.js +++ b/server/src/controllers/UserController.js @@ -31,7 +31,7 @@ const UserController = { scuntTeam, ); } else { - user = await UserServices.createUser( + user = await UserServices.create( email.toLowerCase(), password, firstName, @@ -133,7 +133,7 @@ const UserController = { } catch (error) { req.log.error({ msg: 'User Logout Failure: user ' + user.id, - err, + error, user: user.getResponseObject(), }); next(error); @@ -190,7 +190,7 @@ const UserController = { const result = await UserServices.validateEmailConfirmationToken(emailToken); const existingUser = await UserServices.getUserByEmail(email); - if (!existingUser || existingUser.email !== result) { + if (existingUser.email !== result) { next(new Error('INVALID_VERIFICATION_LINK')); } else { await UserServices.updateUserInfo(existingUser.id, { confirmedEmail: true }); @@ -201,13 +201,13 @@ const UserController = { 'Successfully verified your email! Log in with your email and password to get started.', }); } - } catch (err) { + } catch (error) { req.log.fatal({ msg: 'Error with password reset page: user ' + req.body.email, - err, - user: user.getResponseObject(), + error, + user: req.body, }); - next(err); + next(error); } }, @@ -222,9 +222,9 @@ const UserController = { .send({ message: 'You have been successfully unsubscribed from announcement emails.' }); } catch (error) { req.log.error({ - msg: 'User Announcement Unsubscribe Error: user ' + user.id, - err, - user: user.getResponseObject(), + msg: 'User Announcement Unsubscribe Error: user ' + req.body.email, + error, + user: req.body, }); next(error); } @@ -239,9 +239,9 @@ const UserController = { .send({ message: 'You have been successfully resubscribed to announcement emails.' }); } catch (error) { req.log.error({ - msg: 'User Announcement Resubscribe Error: user ' + user.id, - err, - user: user.getResponseObject(), + msg: 'User Announcement Resubscribe Error: user ' + req?.body?.email, + error, + user: req.body, }); next(error); } @@ -269,9 +269,9 @@ const UserController = { } } catch (err) { req.log.fatal({ - msg: 'User Request Auth Scope Error: user ' + user.id, + msg: 'User Request Auth Scope Error: user ' + req.user.id, err, - user: user.getResponseObject(), + user: req.user, }); next(err); } @@ -330,13 +330,13 @@ const UserController = { const { userAuthScopes } = req.body; await UserServices.updateAuthScopes(userAuthScopes); return res.status(200).send({ message: 'Auth scopes updated!' }); - } catch (err) { + } catch (error) { req.log.error({ - msg: 'Error Updating Auth Scopes: user ' + user.id, - err, - user: updatedUser.getResponseObject(), + msg: 'Error Updating Auth Scopes: user ' + req.user.id, + error, + user: req.user, }); - next(err); + next(error); } }, @@ -365,9 +365,9 @@ const UserController = { const { id } = req.params; await UserServices.deleteUser(id); res.status(200).send({ message: 'Successfully deleted User!', deletedId: id }); - } catch (err) { - req.log.fatal({ msg: 'Error Deleting User ' + id, err }); - next(err); + } catch (error) { + req.log.fatal({ msg: 'Error Deleting User ' + req.id, error }); + next(error); } }, diff --git a/server/src/loaders/mongoLoader.js b/server/src/loaders/mongoLoader.js index 2a075c15..f2e3f964 100644 --- a/server/src/loaders/mongoLoader.js +++ b/server/src/loaders/mongoLoader.js @@ -88,21 +88,6 @@ const froshGroups = [ }, ]; -const ScuntGameSettings = { - name: 'new settings', - minAmountPointsPercent: 0.5, - amountOfTeams: 10, - amountOfStarterBribePoints: 10000, - maxAmountPointsPercent: 0.3, - revealJudgesAndBribes: false, - revealTeams: false, - showDiscordLink: false, - revealLeaderboard: false, - revealMissions: false, - allowJudging: false, - disordLink: 'https://discord.gg/mRutbwuCK9', -}; - const loadMongo = async (app) => { console.log('Loading mongo...'); const { MONGODB_PASSWORD, MONGODB_HOST, MONGODB_USER } = process.env; @@ -121,7 +106,7 @@ const loadMongo = async (app) => { }), ); await FroshServices.initFroshGroups(froshGroups); - await ScuntGameSettingsServices.initScuntGameSettings(ScuntGameSettings); + await ScuntGameSettingsServices.initScuntGameSettings(); }; module.exports = loadMongo; diff --git a/server/src/middlewares/errorResponseMiddleware.js b/server/src/middlewares/errorResponseMiddleware.js index 74cf653f..bee91e19 100644 --- a/server/src/middlewares/errorResponseMiddleware.js +++ b/server/src/middlewares/errorResponseMiddleware.js @@ -28,6 +28,66 @@ function errorResponseMiddleware(err, req, res, next) { } else if (err.message === 'UNAUTHORIZED') { statusCode = 403; errorMessage = 'Unauthorized'; + } else if (err.message === 'SETTINGS_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Settings not found. Initialize the settings first.'; + } else if (err.message === 'INVALID_SETTINGS') { + statusCode = 400; + errorMessage = "Invalid settings. The current settings don't allow you to do this."; + } else if (err.message === 'NO_MISSIONS_FOUND') { + statusCode = 404; + errorMessage = 'No missions found. Add some missions first.'; + } else if (err.message === 'UNABLE_TO_CREATE_MISSION') { + statusCode = 500; + errorMessage = 'Unable to create mission. There was an error in creating the mission.'; + } else if (err.message === 'UNABLE_TO_CREATE_SCUNT_MISSIONS') { + statusCode = 500; + errorMessage = 'Unable to create missions. There was an error in creating the missions.'; + } else if (err.message === 'MISSION_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Mission not found. Please check the mission number.'; + } else if (err.message === 'LEADUR_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Leadur not found.'; + } else if (err.message === 'TEAMS_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Teams not found. Please initialize the teams first.'; + } else if (err.message === 'NOT_ENOUGH_BRIBE_POINTS') { + statusCode = 400; + errorMessage = 'Not enough bribe points. Please ask an exec to give you more.'; + } else if (err.message === 'NOT_ALLOWED_TO_JUDGE') { + statusCode = 400; + errorMessage = 'You are not allowed to judge yet.'; + } else if (err.message === 'INVALID_TEAM_NUMBER') { + statusCode = 400; + errorMessage = 'Invalid team number.'; + } else if (err.message === 'JUDGES_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Judges not found. Please add the judges first.'; + } else if (err.message === 'MISSING_SCUNT_SETTINGS') { + statusCode = 404; + errorMessage = 'Scunt settings are not valid. Please reinitialize them.'; + } else if (err.message === 'SCUNT_FROSH_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Scunt frosh not found. Please add the scunt frosh first.'; + } else if (err.message === 'TEAM_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Team not found. Please check the team number.'; + } else if (err.message === 'TRANSACTIONS_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Transactions not found. Please add the transactions first.'; + } else if (err.message === 'USER_NOT_FOUND') { + statusCode = 404; + errorMessage = 'User not found.'; + } else if (err.message === 'USERS_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Users not found.'; + } else if (err.message === 'UNABLE_TO_UPDATE_SCUNT_SETTINGS') { + statusCode = 400; + errorMessage = 'Unable to update scunt settings. Please input valid values.'; + } else if (err.message === 'FROSH_NOT_FOUND') { + statusCode = 404; + errorMessage = 'Frosh not found. They might not be registered.'; } else { statusCode = 500; errorMessage = 'whoops we have no idea what happened!?'; diff --git a/server/src/models/AnnouncementModel.js b/server/src/models/AnnouncementModel.js index 8af74150..6ac2ed03 100644 --- a/server/src/models/AnnouncementModel.js +++ b/server/src/models/AnnouncementModel.js @@ -22,5 +22,8 @@ const AnnouncementSchema = new mongoose.Schema({ }); const AnnouncementModel = mongoose.model('Announcement', AnnouncementSchema); - +/** + * Global Announcement objet + * @typedef {typeof AnnouncementModel.schema.obj} Announcement + */ module.exports = AnnouncementModel; diff --git a/server/src/models/FaqModel.js b/server/src/models/FaqModel.js index 34a28252..10ba4753 100644 --- a/server/src/models/FaqModel.js +++ b/server/src/models/FaqModel.js @@ -27,5 +27,8 @@ const FaqSchema = new Schema( ); const FaqModel = mongoose.model('FAQ', FaqSchema); - +/** + * Global Faq objet + * @typedef {typeof FaqModel.schema.obj} Faq + */ module.exports = FaqModel; diff --git a/server/src/models/FroshModel.js b/server/src/models/FroshModel.js index 311638f2..da5f154a 100644 --- a/server/src/models/FroshModel.js +++ b/server/src/models/FroshModel.js @@ -188,6 +188,11 @@ const FroshSchema = new mongoose.Schema( required: false, default: false, }, + gotFood: { + type: Boolean, + required: false, + default: false, + }, }, { discriminatorKey: 'userType' }, ); diff --git a/server/src/models/ScuntGameSettingsModel.js b/server/src/models/ScuntGameSettingsModel.js index 65cc6ade..f8fac4c5 100644 --- a/server/src/models/ScuntGameSettingsModel.js +++ b/server/src/models/ScuntGameSettingsModel.js @@ -5,7 +5,7 @@ const ScuntGameSettingSchema = new mongoose.Schema({ name: { type: String, required: true, - default: 'Scunt 2T2 Settings', + default: 'Scunt 2T3 Settings', }, amountOfTeams: { type: Number, @@ -40,16 +40,16 @@ const ScuntGameSettingSchema = new mongoose.Schema({ required: false, default: false, }, - showDiscordLink: { - type: Boolean, - required: false, - default: false, - }, - discordLink: { - type: String, - required: true, - default: 'https://discord.gg/mRutbwuCK9', - }, + // showDiscordLink: { + // type: Boolean, + // required: false, + // default: false, + // }, + // discordLink: { + // type: String, + // required: true, + // default: 'https://discord.gg/mRutbwuCK9', + // }, revealLeaderboard: { type: Boolean, required: false, @@ -68,7 +68,7 @@ const ScuntGameSettingSchema = new mongoose.Schema({ scuntDate: { type: String, required: false, - default: 'September 7, 2022 18:00:00', + default: 'September 6, 2023 18:00:00', }, }); diff --git a/server/src/models/ScuntTeamModel.js b/server/src/models/ScuntTeamModel.js index f098d7b9..cecf5600 100644 --- a/server/src/models/ScuntTeamModel.js +++ b/server/src/models/ScuntTeamModel.js @@ -1,9 +1,9 @@ const mongoose = require('mongoose'); - +const formatInteger = (value) => parseInt(value || 0, 10); const ScuntTeamTransactionsSchema = new mongoose.Schema( { name: { type: String, default: '' }, - points: { type: Number, default: 0 }, + points: { type: Number, default: 0, set: formatInteger }, missionNumber: { type: Number, default: -1, index: true }, }, { timestamps: true }, @@ -27,6 +27,7 @@ const ScuntTeamSchema = new mongoose.Schema({ type: Number, required: true, default: 0, + set: formatInteger, }, transactions: [ScuntTeamTransactionsSchema], }); diff --git a/server/src/routes/qrRoutes.js b/server/src/routes/qrRoutes.js index ca8ea3fd..e923e533 100644 --- a/server/src/routes/qrRoutes.js +++ b/server/src/routes/qrRoutes.js @@ -48,4 +48,6 @@ router.put( router.put('/prekit', checkLoggedIn, hasAuthScopes(['scanner:kits']), QRController.preKitPickUp); +router.put('/food', checkLoggedIn, hasAuthScopes(['scanner:food']), QRController.getFood); + module.exports = router; diff --git a/server/src/routes/scuntTeamRoutes.js b/server/src/routes/scuntTeamRoutes.js index 12404fa6..7a27b96f 100644 --- a/server/src/routes/scuntTeamRoutes.js +++ b/server/src/routes/scuntTeamRoutes.js @@ -120,7 +120,7 @@ router.post( router.post( '/transactions', checkLoggedIn, - hasAuthScopes(['scunt:exec view transactions']), + // hasAuthScopes(['scunt:exec view transactions']), ScuntTeamController.viewTransactions, ); diff --git a/server/src/services/AnnouncementServices.js b/server/src/services/AnnouncementServices.js index 5d0cf4da..fa6a7fee 100644 --- a/server/src/services/AnnouncementServices.js +++ b/server/src/services/AnnouncementServices.js @@ -1,112 +1,165 @@ +/** + * Global Announcement objet + * @typedef {import("../models/AnnouncementModel").Announcement} Announcement + */ const AnnouncementModel = require('../models/AnnouncementModel'); const UserModel = require('../models/UserModel'); const announcementSubscription = require('../subscribers/announcementSubscription'); const AnnouncementServices = { - async getAllAnnouncements() { - return new Promise((resolve, reject) => { - AnnouncementModel.find({}, (err, announcements) => { - if (err) { - reject(err); - } else { - resolve(announcements); - } - }).sort({ dateCreated: -1 }); - }); + /** + * @description Gets all announcements + * @returns {Announcement[]} All announcements + */ + async getAll() { + return AnnouncementModel.find({}) + .sort({ dateCreated: -1 }) + .then( + (announcements) => { + return announcements; + }, + (error) => { + throw new Error('UNABLE_TO_GET_ALL_ANNOUNCEMENTS', { cause: error }); + }, + ); }, - async completeAnnouncementElement(id, currentUser) { + /** + * @description marks an announcement as completed for a user OR removes it from the completed list + * @param {String} id announcement id + * @param {String} userID current user id + * @returns {User} updated user + */ + async complete(id, userID) { + const currentUser = await UserModel.findOne({ _id: userID }).then( + (user) => { + if (!user) throw new Error('USER_NOT_FOUND'); + return user; + }, + (error) => { + throw new Error('UNABLE_TO_GET_USER', { cause: error }); + }, + ); var listOfCompleted = currentUser.completedAnnouncements; - return new Promise((resolve, reject) => { - AnnouncementModel.findOne({ _id: id }, (err, announcement) => { - if (err) { - reject(err); - } else { - let removeIndex; - if ( - listOfCompleted.every((value, index) => { - if (value.id === announcement.id) { - removeIndex = index; - } - return value.id != announcement.id; - }) - ) { - listOfCompleted.push({ _id: announcement.id, announcementName: announcement.name }); - } else { - listOfCompleted.splice(removeIndex, 1); - } - - UserModel.findOneAndUpdate( - { _id: currentUser._id }, - { completedAnnouncements: listOfCompleted }, - (err, user) => { - if (err || !user) { - reject('UNABLE_TO_UPDATE_USER'); - } else { - resolve(user); - } - }, - ); + const completedAnnouncement = await AnnouncementModel.findOne({ _id: id }).then( + (announcement) => { + if (!announcement) throw new Error('ANNOUNCEMENT_NOT_FOUND'); + return announcement; + }, + (error) => { + throw new Error('UNABLE_TO_GET_ANNOUNCEMENT', { cause: error }); + }, + ); + let removeIndex; + if ( + listOfCompleted.every((value, index) => { + if (value.announcementID === completedAnnouncement.id) { + removeIndex = index; } + return value.announcementID != completedAnnouncement.id; + }) + ) { + listOfCompleted.push({ + announcementID: completedAnnouncement.id, + announcementName: completedAnnouncement.name, }); - }); + } else { + listOfCompleted.splice(removeIndex, 1); + } + currentUser.completedAnnouncements = listOfCompleted; + return currentUser.save().then( + (user) => { + return user.completedAnnouncements; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_USER', { cause: error }); + }, + ); }, - async getCompletedAnnouncements(currentUser) { - return new Promise((resolve, reject) => { - AnnouncementModel.find( - { - _id: { $in: currentUser.completedAnnouncements }, - }, - (err, announcements) => { - if (err) { - reject(err); - } else { - resolve(announcements); - } + /** + * @description Gets all announcements that have been completed by a user + * @param {user} currentUser current user + * @returns {Announcement[]} + */ + async getCompleted(id) { + const currentUser = await UserModel.findOne({ _id: id }).then( + (user) => { + if (!user) throw new Error('USER_NOT_FOUND'); + return user; + }, + (error) => { + throw new Error('UNABLE_TO_GET_USER', { cause: error }); + }, + ); + return AnnouncementModel.find({ + _id: { $in: currentUser.completedAnnouncements.map((value) => value.announcementID) }, + }) + .sort({ dateCreated: -1 }) + .then( + (announcements) => announcements, + (error) => { + throw new Error('UNABLE_TO_GET_COMPLETED_ANNOUNCEMENTS', { cause: error }); }, - ).sort({ dateCreated: -1 }); - }); + ); }, - async updateAnnouncementElement(id, announcementElement) { - return new Promise((resolve, reject) => { - AnnouncementModel.findOneAndUpdate({ _id: id }, announcementElement, (err, announcement) => { - if (err || !announcement) { - reject('UNABLE_TO_UPDATE_ANNOUNCEMENT'); - } else { - resolve(announcement); + /** + * @description Creates a new announcement + * @param {Announcement} announcementElement new announcement to be created + * @returns {Announcement} + */ + async create(announcementElement) { + return AnnouncementModel.create(announcementElement).then( + (newAnnouncement) => { + if (announcementElement.sendAsEmail === true) { + announcementSubscription.add(newAnnouncement); } - }); - }); + return newAnnouncement; + }, + (error) => { + throw new Error('UNABLE_TO_CREATE_ANNOUNCEMENT', { cause: error }); + }, + ); }, - async saveNewAnnouncementElement(announcementElement) { - return new Promise((resolve, reject) => { - AnnouncementModel.create(announcementElement, (err, newAnnouncement) => { - if (err) { - reject(err); - } else { - if (announcementElement.sendAsEmail === true) { - announcementSubscription.add(announcementElement); - } - resolve(newAnnouncement); - } - }); - }); + /** + * @description Updates an announcement + * @param {String} id announcement id + * @param {Announcement} announcementElement announcement fields to be updated + * @returns {Announcement} + */ + async update(id, announcementElement) { + return AnnouncementModel.findOneAndUpdate( + { _id: id }, + { ...announcementElement }, + { new: true }, + ).then( + (announcement) => { + if (!announcement) throw new Error('ANNOUNCEMENT_NOT_FOUND'); + return announcement; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_ANNOUNCEMENT', { cause: error }); + }, + ); }, - async deleteAnnouncementElement(id) { - return new Promise((resolve, reject) => { - AnnouncementModel.findOneAndDelete({ _id: id }, (err, deleteAnnouncement) => { - if (err || !deleteAnnouncement) { - reject('UNABLE_TO_DELETE_ANNOUNCEMENT'); - } else { - resolve(deleteAnnouncement); - } - }); - }); + /** + * @description Deletes an announcement + * @param {String} id announcement id + * @returns {Announcement} + */ + async delete(id) { + return AnnouncementModel.findOneAndDelete({ _id: id }).then( + (deletedAnnouncement) => { + if (!deletedAnnouncement) throw new Error('ANNOUNCEMENT_NOT_FOUND'); + return deletedAnnouncement; + }, + (error) => { + throw new Error('UNABLE_TO_DELETE_ANNOUNCEMENT', { cause: error }); + }, + ); }, }; - module.exports = AnnouncementServices; diff --git a/server/src/services/FaqServices.js b/server/src/services/FaqServices.js index 5a566d99..622bbf1b 100644 --- a/server/src/services/FaqServices.js +++ b/server/src/services/FaqServices.js @@ -1,129 +1,124 @@ +/** + * Global Faq objet + * @typedef {import("../models/FaqModel").Faq} Faq + */ const FaqModel = require('../models/FaqModel'); -const mongoose = require('mongoose'); const FaqServices = { /** - * Gets all the questions (answered and unanswered) in mongo. - * @async - * @return {Promise>} - all the questions + * @description Gets all the questions. + * @return {Faq[]} all the questions */ - async getAllQuestions() { - return new Promise((resolve, reject) => { - FaqModel.find({ deleted: false }, (err, faqs) => { - if (err) { - reject(err); - } else { - resolve(faqs); - } - }); - }); + async getAll() { + return FaqModel.find({ deleted: false }).then( + (faqs) => { + if (!faqs.length) throw new Error('FAQS_NOT_FOUND'); + return faqs; + }, + (error) => { + throw new Error('UNABLE_TO_GET_FAQS', { cause: error }); + }, + ); }, /** - * Gets all the answered questions in mongo. - * @async - * @return {Promise>} - all the answered questions + * @description Gets all the answered questions. + * @returns {Faq[]} */ - async getAnsweredQuestions() { - return new Promise((resolve, reject) => { - FaqModel.find({ isAnswered: true, deleted: false }, (err, faqs) => { - if (err) { - reject(err); - } else { - resolve(faqs); - } - }); - }); + async getAnswered() { + return FaqModel.find({ isAnswered: true, deleted: false }).then( + (faqs) => { + if (!faqs.length) throw new Error('FAQS_NOT_FOUND'); + return faqs; + }, + (error) => { + throw new Error('UNABLE_TO_GET_ANSWERED_FAQS', { cause: error }); + }, + ); }, /** - * Gets all the unanswered questions in mongo. - * @async - * @return {Promise>} - all the unanswered questions + * @description Gets all the unanswered questions. + * @returns {Faq[]} */ - async getUnansweredQuestions() { - return new Promise((resolve, reject) => { - FaqModel.find({ isAnswered: false, deleted: false }, (err, faqs) => { - if (err) { - reject(err); - } else { - resolve(faqs); - } - }); - }); + async getUnanswered() { + return FaqModel.find({ isAnswered: false, deleted: false }).then( + (faqs) => { + if (!faqs.length) throw new Error('FAQS_NOT_FOUND'); + return faqs; + }, + (error) => { + throw new Error('UNABLE_TO_GET_UNANSWERED_FAQS', { cause: error }); + }, + ); }, /** - * Creates a new question in mongo. - * @param {String} question - the question being asked - * @param {String} category - the category of the question being asked - * @async - * @return {Promise} - the new question + * @description Creates a new question and returns the question. + * @param {String} email email of the user + * @param {String} question question asked by the user + * @param {String} answer answer to the question + * @param {String} category category of the question + * @returns {Faq} */ - async createNewQuestion(email, question, answer, category) { - return new Promise((resolve, reject) => { - let doc = {}; - if (answer) { - if (category) { - doc = { email, question, answer, category, isAnswered: true }; - } else { - doc = { email, question, answer, isAnswered: true }; - } - } else if (category) { - doc = { email, question, category }; + async create(email, question, answer, category) { + let doc = {}; + if (answer) { + if (category) { + doc = { email, question, answer, category, isAnswered: true }; } else { - doc = { email, question }; + doc = { email, question, answer, isAnswered: true }; } - //const doc = category ? { email, question, category } : { email, question }; - FaqModel.create(doc, (err, newFaq) => { - if (err) { - reject(err); - } else { - resolve(newFaq); - } - }); - }); + } else if (category) { + doc = { email, question, category }; + } else { + doc = { email, question }; + } + + return FaqModel.create(doc).then( + (faq) => faq, + (error) => { + throw new Error('UNABLE_TO_CREATE_FAQ', { cause: error }); + }, + ); }, /** - * Soft deletes a question by id. - * @param {ObjectId} faqId - id of the FAQ to be deleted - * @async - * @return {Promise} - the FAQ which was deleted + * @description Soft deletes a question by id. + * @param {String} faqId - id of the FAQ to be deleted + * @return {Faq} - the FAQ which was deleted */ - async deleteQuestion(faqId) { - return new Promise((resolve, reject) => { - FaqModel.findByIdAndUpdate(faqId, { deleted: true }, (err, faq) => { - if (err || !faq) { - reject('UNABLE_TO_DELETE_FAQ'); - } else { - resolve(faq); - } - }); - }); + async delete(faqId) { + return FaqModel.findByIdAndUpdate(faqId, { deleted: true }).then( + (faq) => { + if (!faq) throw new Error('FAQ_NOT_FOUND'); + return faq; + }, + (error) => { + throw new Error('UNABLE_TO_DELETE_FAQ', { cause: error }); + }, + ); }, /** - * Updates a question by ID, and creates a new one if the ID is null or undefined - * @param {ObjectId|null|undefined} faqId - id of the FAQ to be updated - * @param {Object} update - the update to be made to the FAQ - * @return {Promise} - the updated FAQ + * @description Updates a question by ID, and creates a new one if the ID is null or undefined + * @param {String|null|undefined} faqId - id of the FAQ to be updated + * @param {Faq} update - the update to be made to the FAQ + * @return {Faq} - the updated FAQ */ - async updateQuestion(faqId, update) { - return new Promise((resolve, reject) => { - FaqModel.findOneAndUpdate( - { _id: faqId ?? new mongoose.Types.ObjectId() }, - update, - { upsert: true, new: true, runValidators: true }, - (err, faq) => { - if (err || !faq) { - reject('UNABLE_TO_UPDATE_FAQ'); - } else { - resolve(faq); - } - }, - ); - }); + async update(faqId, update) { + return FaqModel.findByIdAndUpdate(faqId, update, { + new: true, + runValidators: true, + }).then( + (faq) => { + if (!faq) throw new Error('FAQ_NOT_FOUND'); + return faq; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_FAQ', { cause: error }); + }, + ); }, }; diff --git a/server/src/services/FroshServices.js b/server/src/services/FroshServices.js index f5d52d9f..70dc281b 100644 --- a/server/src/services/FroshServices.js +++ b/server/src/services/FroshServices.js @@ -4,7 +4,7 @@ const UserModel = require('../models/UserModel'); const FroshServices = { /** - * Gets the frosh group for a new frosh. + * @description Gets the frosh group for a new frosh. * @param {String} discipline - the discipline of the frosh * @param {String} pronouns - the pronouns of the frosh * @return {Promise} - the name of the frosh group @@ -35,7 +35,7 @@ const FroshServices = { }, /** - * Upgrades an existing user account to a frosh account. + * @description Upgrades an existing user account to a frosh account. * @param {Object} user - the existing user document * @param {Object} newInfo - the new info required to register the frosh * @param {String} paymentIntent @@ -58,127 +58,122 @@ const FroshServices = { return await frosh.save(); }, + /** + * @description Adds a payment to the user's payment history for the retreat. + * @param {User} user current user + * @param {Payment} paymentIntent Payment object from stripe + * @returns {User} updated user + */ async addRetreatPayment(user, paymentIntent) { - return new Promise((resolve, reject) => { - FroshModel.findByIdAndUpdate( - user.id, - { - $push: { - payments: [ - { - item: 'Retreat Ticket', - paymentIntent: paymentIntent.toString(), - amountDue: 9500, - }, - ], + return FroshModel.findByIdAndUpdate(user.id, { + $push: { + payments: [ + { + item: 'Retreat Ticket', + paymentIntent: paymentIntent.toString(), + amountDue: 9500, }, - }, - {}, - (err, user) => { - if (err) { - reject(err); - } else if (!user) { - reject('INVALID_USER'); - } else { - resolve(user); - } - }, - ); - }); + ], + }, + }).then( + (frosh) => frosh, + (error) => { + throw new Error('UNABLE_TO_ADD_PAYMENT', { cause: error }); + }, + ); }, /** - * Get a frosh by their id - * @param id - * @return {Promise} + * @description Gets the frosh info from ID. + * @param {String} id user id + * @returns {User} */ async getFroshInfo(id) { - return FroshModel.findById(id); + return FroshModel.findById(id).then( + (frosh) => frosh, + (error) => { + throw new Error('UNABLE_TO_GET_FROSH', { cause: error }); + }, + ); }, /** - * Initializes a list of frosh groups with default values in the database. - * @constructor - * @param {Array} groups - List of frosh groups as javascript objects + * @description Initializes the frosh groups in the database. + * @param {Object[]} groups an array of frosh groups + * @returns {FroshGroup[]} */ async initFroshGroups(groups) { - return await Promise.all( + return Promise.all( groups.map((group) => { - return new Promise((resolve, reject) => { - FroshGroupModel.findOneAndUpdate( - { name: group.name }, - { ...group }, - { upsert: true }, - (err, result) => { - if (err) { - reject(err); - } else { - resolve(result); - } - }, - ); - }); + return FroshGroupModel.findOneAndUpdate( + { name: group.name }, + { ...group }, + { upsert: true }, + ).then( + (result) => result, + (error) => { + throw new Error(`UNABLE_TO_INIT_FROSH_GROUP: ${group.name}`, { cause: error }); + }, + ); }), ); }, + /** + * @description Updates the user info. + * @param {String} userId user id + * @param {User} updateInfo updated user info + * @returns {User} + */ async updateFroshInfo(userId, updateInfo) { - return new Promise((resolve, reject) => { - FroshModel.findOneAndUpdate( - { _id: userId }, - updateInfo, - { returnDocument: 'after' }, - (err, Frosh) => { - if (err) { - reject(new Error('UNABLE_TO_UPDATE_FROSH', { cause: err })); - } else if (!Frosh) { - reject(new Error('FROSH_NOT_FOUND')); - } else { - resolve(Frosh); - } - }, - ); - }); + return FroshModel.findByIdAndUpdate(userId, updateInfo, { + new: true, + returnDocument: 'after', + }).then( + (frosh) => { + if (!frosh) throw new Error('FROSH_NOT_FOUND'); + return frosh; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_FROSH', { cause: error }); + }, + ); }, + /** + * @description Gets all frosh matching query. + * @param {Object} query query object + * @param {Object} projection projection object + * @returns {User[]} + */ async getFilteredFroshInfo(query, projection) { - return new Promise((resolve, reject) => { - FroshModel.find( - query, - { ...projection, isRegistered: 1 }, - { strictQuery: false }, - (err, frosh) => { - if (err) { - reject(err); - } else if (!frosh) { - reject('FROSH_NOT_FOUND'); - } else { - resolve(frosh); - } - }, - ); - }); + return FroshModel.find(query, { ...projection, isRegistered: 1 }, { strictQuery: false }).then( + (frosh) => { + if (!frosh.length) throw new Error('FROSH_NOT_FOUND'); + return frosh; + }, + (error) => { + throw new Error('UNABLE_TO_GET_FROSH', { cause: error }); + }, + ); }, + /** + * @description Gets all users matching query. + * @param {Object} query query object + * @param {Object} projection projection object + * @returns {User[]} + */ async getFilteredUserInfo(query, projection) { - return new Promise((resolve, reject) => { - UserModel.find( - query, - { ...projection, isRegistered: 1 }, - { strictQuery: false }, - (err, frosh) => { - if (err) { - reject(err); - } else if (!frosh) { - reject('INTERNAL_ERROR'); - } else { - resolve(frosh); - } - }, - ); - }); + return UserModel.find(query, { ...projection, isRegistered: 1 }, { strictQuery: false }).then( + (user) => user, + (error) => { + throw new Error('UNABLE_TO_GET_USER', { cause: error }); + }, + ); }, + /* istanbul ignore next */ async mapFroshUsers(frosh) { // Recreating froshGroupList, to not include the broken ones const froshGroupList = await FroshGroupModel.find(); diff --git a/server/src/services/LeadurServices.js b/server/src/services/LeadurServices.js index cb773ff5..7fd9383c 100644 --- a/server/src/services/LeadurServices.js +++ b/server/src/services/LeadurServices.js @@ -1,61 +1,79 @@ const bcrypt = require('bcrypt'); const LeadurModel = require('../models/LeadurModel'); const emailConfirmationSubscription = require('../subscribers/emailConfirmationSubscription'); +const jwt = require('jsonwebtoken'); + +/** + * @description Creates an email confirmation token for a user + * @param {string} email + * @returns {Token} + */ +function generateEmailConfirmationToken(email) { + return jwt.sign(email, process.env.JWT_EMAIL_CONFIRMATION_TOKEN); +} const LeadurServices = { /** - * Creates a new user with type Leadur. + * @description Creates a new user with type Leadur. * @param {String} email * @param {String} password * @param {String} firstName * @param {String} lastName * @param {String} preferredName * @param {Number} scuntTeam - * @return {Promise} + * @return {Leedur} */ async createLeadur(email, password, firstName, lastName, preferredName, scuntTeam) { - return new Promise((resolve, reject) => { - bcrypt - .hash(password, 10) - .then((hashedPassword) => { - LeadurModel.create( - { email, hashedPassword, firstName, lastName, preferredName, scuntTeam }, - async (err, newUser) => { - if (err) { - reject(err); - } else { - emailConfirmationSubscription.add(newUser); - resolve(newUser); - } - }, - ); - }) - .catch((err) => { - reject(err); - }); - }); + const hashedPassword = await bcrypt.hash(password, 10).then( + (hashedPassword) => hashedPassword, + (error) => { + throw new Error('UNABLE_TO_HASH_PASSWORD', { cause: error }); + }, + ); + + return LeadurModel.create({ + email, + hashedPassword, + firstName, + lastName, + preferredName, + scuntTeam, + }).then( + (newLeedur) => { + const token = generateEmailConfirmationToken(email); + emailConfirmationSubscription.add({ token, email }); + return newLeedur; + }, + (error) => { + throw new Error('UNABLE_TO_CREATE_LEEDUR', { cause: error }); + }, + ); }, - async requestScopesAndData(user, requestedFields, requestedAuthScopes) { - return new Promise((resolve, reject) => { - LeadurModel.findByIdAndUpdate( - user.id, - { - 'froshDataFields.requested': requestedFields, - 'authScopes.requested': requestedAuthScopes, - }, - { returnDocument: 'after' }, - (err, leadur) => { - if (err) { - reject(err); - } else if (!leadur) { - reject('INVALID_USER'); - } else { - resolve(leadur); - } - }, - ); - }); + /** + * @description Update leedur permissions + * @param {String} userID leeduur to update + * @param {String[]} requestedFields fields requested by user + * @param {String[]} requestedAuthScopes auth scopes requested by user + * @returns {Leedur} updated leedur + */ + async requestScopesAndData(userID, requestedFields, requestedAuthScopes) { + return LeadurModel.findByIdAndUpdate( + userID, + { + 'froshDataFields.requested': requestedFields, + 'authScopes.requested': requestedAuthScopes, + }, + { returnDocument: 'after' }, + ).then( + (updatedLeedur) => { + if (!updatedLeedur) throw new Error('USER_NOT_FOUND'); + return updatedLeedur; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_LEEDUR', { cause: error }); + }, + ); }, }; diff --git a/server/src/services/PaymentServices.js b/server/src/services/PaymentServices.js index af80d246..e4f1d3e0 100644 --- a/server/src/services/PaymentServices.js +++ b/server/src/services/PaymentServices.js @@ -5,7 +5,7 @@ const FroshGroupModel = require('../models/FroshGroupModel'); const PaymentServices = { /** - * Decodes a webhook event from stripe and verifies that it was sent by stripe + * @description Decodes a webhook event from stripe and verifies that it was sent by stripe * @param {Buffer} data * @param {String} signature * @return {Promise} @@ -14,69 +14,91 @@ const PaymentServices = { const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET; try { return await stripe.webhooks.constructEventAsync(data, signature, endpointSecret); - } catch (err) { - console.log('Stripe webhook verification failed', err.message); - throw err; + } catch (error) { + console.error('Stripe webhook verification failed', error); + throw new Error('UNABLE_TO_VERIFY_STRIPE_WEBHOOK', { cause: error }); } }, /** - * Updates a payment for a given frosh. + * @description Updates a payment for a given frosh. * @param {String} paymentId * @param {Number} amountReceived * @return {Promise> & Omit & {_id: Omit["_id"]}, Document> & Omit & {_id: Omit["_id"]}, {}, Omit>>} */ async updatePayment(paymentId, amountReceived) { - try { - const frosh = await FroshModel.findOne({ 'payments.paymentIntent': paymentId }); - if (frosh) { - frosh.authScopes = { requested: [], approved: [] }; - const idx = frosh.payments.findIndex((p) => p.paymentIntent === paymentId); - frosh.payments[idx].amountDue = frosh.payments[idx].amountDue - amountReceived; - if (frosh.payments[idx].item === 'Orientation Ticket') { - frosh.isRegistered = true; - } else if (frosh.payments[idx].item === 'Retreat Ticket') { - frosh.isRetreat = true; - } - //TODO: update frosh balance - await frosh.save({ validateModifiedOnly: true }); - console.log('Frosh payment completed! Frosh info: ', frosh); - await FroshGroupModel.findOneAndUpdate( - { name: frosh.froshGroup }, - { $inc: { totalNum: 1 } }, - { new: true }, - ).then((doc) => { - console.log(`Group ${doc.name} total: ${doc.totalNum}`); - }); + const frosh = await FroshModel.findOne({ 'payments.paymentIntent': paymentId }).then( + (frosh) => { + if (!frosh) throw new Error('FROSH_NOT_FOUND'); return frosh; - } - return null; - } catch (e) { - console.log(e); - throw new Error('Error updating payment', { cause: e }); + }, + (error) => { + throw new Error('UNABLE_TO_FIND_FROSH', { cause: error }); + }, + ); + frosh.set({ authScopes: { requested: [], approved: [] } }); + const idx = frosh.payments.findIndex((p) => p.paymentIntent === paymentId); + frosh.payments[idx].amountDue = frosh.payments[idx].amountDue - amountReceived; + if (frosh.payments[idx].item === 'Orientation Ticket') { + frosh.set({ isRegistered: true }); + await frosh.save({ validateModifiedOnly: true }).then( + (frosh) => frosh, + (error) => { + throw new Error('UNABLE_TO_UPDATE_FROSH', { cause: error }); + }, + ); + console.log('Frosh payment completed! Frosh info: ', frosh); + return FroshGroupModel.findOneAndUpdate( + { name: frosh.froshGroup }, + { $inc: { totalNum: 1 } }, + { new: true }, + ).then( + (doc) => { + if (!doc) console.log(new Error('FROSH_GROUP_NOT_FOUND')); + else console.log(`Group ${doc.name} total: ${doc.totalNum}`); + return frosh; + }, + (error) => { + console.log(new Error('UNABLE_TO_UPDATE_FROSH_GROUP', { cause: error })); + return frosh; + }, + ); + } else if (frosh.payments[idx].item === 'Retreat Ticket') { + frosh.set({ isRetreat: true }); + return frosh.save({ validateModifiedOnly: true }).then( + (frosh) => frosh, + (error) => { + throw new Error('UNABLE_TO_UPDATE_FROSH', { cause: error }); + }, + ); + } else { + throw new Error('UNABLE_TO_UPDATE_FROSH', { cause: new Error('INVALID_PAYMENT_ITEM') }); } }, + /** + * @description Gets the number of non-expired payments for a given item. + * @param {Object} item payment item + * @returns {Number} number of non-expired payments for a given item + */ async getNonExpiredPaymentsCountForItem(item) { - return new Promise((resolve, reject) => { - FroshModel.where({ payments: { $elemMatch: { item, expired: false } } }).count( - (err, count) => { - if (err) { - reject(err); - } else { - resolve(count); - } - }, - ); - }); + return FroshModel.countDocuments({ + payments: { $elemMatch: { item, expired: false } }, + }).then( + (count) => count, + (error) => { + throw new Error('UNABLE_TO_GET_COUNT_OF_PAYMENTS', { cause: error }); + }, + ); }, /** - * Creates a checkout session for a user to pay with. + * @description Creates a checkout session for a user to pay with. * @param {String} email * @param {String} type * @return {Promise} */ + /* istanbul ignore next */ async createCheckoutSession(email, type = 'orientation') { const products = { orientation: { @@ -90,75 +112,91 @@ const PaymentServices = { relativeUrlFailure: '/payment-error-retreat', }, }; - try { - return await stripe.checkout.sessions.create({ - customer_email: email, - submit_type: 'pay', - expires_at: type === 'retreat' ? Math.floor(Date.now() / 1000 + 30 * 60) : undefined, - billing_address_collection: 'auto', - line_items: [ - { - price: products[type]?.priceId ?? products['orientation'].priceId, - quantity: 1, - }, - ], - mode: 'payment', - success_url: `${process.env.CLIENT_BASE_URL}${ - products[type]?.relativeUrlSuccess ?? products['orientation'].relativeUrlSuccess - }`, - cancel_url: `${process.env.CLIENT_BASE_URL}${ - products[type]?.relativeUrlFailure ?? products['orientation'].relativeUrlFailure - }`, - }); - } catch (err) { - if (err.raw?.code === 'coupon_expired') { - try { - return await stripe.checkout.sessions.create({ - customer_email: email, - submit_type: 'pay', - expires_at: type === 'retreat' ? Math.floor(Date.now() / 1000 + 30 * 60) : undefined, - billing_address_collection: 'auto', - line_items: [ - { - price: products[type]?.priceId ?? products['orientation'].priceId, - quantity: 1, - }, - ], - mode: 'payment', - success_url: `${process.env.CLIENT_BASE_URL}${ - products[type]?.relativeUrlSuccess ?? products['orientation'].relativeUrlSuccess - }`, - cancel_url: `${process.env.CLIENT_BASE_URL}${ - products[type]?.relativeUrlFailure ?? products['orientation'].relativeUrlFailure - }`, - }); - } catch (e) { - console.log('Error creating checkout session', e.message); - } - } - console.log('Error creating checkout session', err.message); - throw err; - } + // try { + return stripe.checkout.sessions.create({ + customer_email: email, + submit_type: 'pay', + expires_at: type === 'retreat' ? Math.floor(Date.now() / 1000 + 30 * 60) : undefined, + billing_address_collection: 'auto', + line_items: [ + { + price: products[type]?.priceId ?? products['orientation'].priceId, + quantity: 1, + }, + ], + mode: 'payment', + success_url: `${process.env.CLIENT_BASE_URL}${ + products[type]?.relativeUrlSuccess ?? products['orientation'].relativeUrlSuccess + }`, + cancel_url: `${process.env.CLIENT_BASE_URL}${ + products[type]?.relativeUrlFailure ?? products['orientation'].relativeUrlFailure + }`, + }); + // } catch (error) { + // if (error.raw?.code === 'coupon_expired') { + // try { + // return await stripe.checkout.sessions.create({ + // customer_email: email, + // submit_type: 'pay', + // expires_at: type === 'retreat' ? Math.floor(Date.now() / 1000 + 30 * 60) : undefined, + // billing_address_collection: 'auto', + // line_items: [ + // { + // price: products[type]?.priceId ?? products['orientation'].priceId, + // quantity: 1, + // }, + // ], + // mode: 'payment', + // success_url: `${process.env.CLIENT_BASE_URL}${ + // products[type]?.relativeUrlSuccess ?? products['orientation'].relativeUrlSuccess + // }`, + // cancel_url: `${process.env.CLIENT_BASE_URL}${ + // products[type]?.relativeUrlFailure ?? products['orientation'].relativeUrlFailure + // }`, + // }); + // } catch (e) { + // console.log('Error creating checkout session', e.message); + // throw new Error('UNABLE_TO_CREATE_CHECKOUT_SESSION', { cause: e }); + // } + // } + // console.log('Error creating checkout session', error.message); + // throw new Error('UNABLE_TO_CREATE_CHECKOUT_SESSION', { cause: error }); + // } }, + /** + * @description Expires a checkout session. + * @param {Object} paymentIntent payment intent object + * @returns {Frosh} + */ async expirePayment(paymentIntent) { - try { - const frosh = await FroshModel.findOne({ 'payments.paymentIntent': paymentIntent }); - if (!frosh) { - return null; - } - frosh.authScopes = { requested: [], approved: [] }; - frosh.payments.forEach((p) => { - if (p.paymentIntent === paymentIntent) { - p.expired = true; + const frosh = await FroshModel.findOne({ 'payments.paymentIntent': paymentIntent }).then( + (frosh) => { + if (!frosh) { + throw new Error('FROSH_NOT_FOUND'); } - }); - await frosh.save({ validateModifiedOnly: true }); - return frosh; - } catch (e) { - console.log(e); - throw e; - } + return frosh; + }, + (error) => { + throw new Error('UNABLE_TO_FIND_FROSH', { cause: error }); + }, + ); + + frosh.set({ authScopes: { requested: [], approved: [] } }); + frosh.set({ + payments: frosh.payments.map((payment) => { + if (payment.paymentIntent === paymentIntent) { + payment.expired = true; + } + return payment; + }), + }); + return frosh.save({ validateModifiedOnly: true }).then( + (frosh) => frosh, + (error) => { + throw new Error('UNABLE_TO_UPDATE_FROSH', { cause: error }); + }, + ); }, }; diff --git a/server/src/services/ScuntGameSettingsServices.js b/server/src/services/ScuntGameSettingsServices.js index 2cefadd6..a10dfda8 100644 --- a/server/src/services/ScuntGameSettingsServices.js +++ b/server/src/services/ScuntGameSettingsServices.js @@ -1,62 +1,49 @@ -/* eslint-disable no-unused-vars */ - const ScuntGameSettingModel = require('../models/ScuntGameSettingsModel'); const ScuntSettingsSubscription = require('../subscribers/scuntGameSettingsSubscription'); const ScuntGameSettingsServices = { - // default scunt settings set in loaders > mongoLoader.js - async initScuntGameSettings(settings) { - return new Promise((resolve, reject) => { - ScuntGameSettingModel.findOne({}, {}, {}, (err, result) => { - if (err) { - reject(err); - } else { - if (!result) { - ScuntGameSettingModel.create( - { - name: settings.name, - amountOfTeams: settings.amountOfTeams, - amountOfStarterBribePoints: settings.amountOfStarterBribePoints, - maxAmountPointsPercent: settings.maxAmountPointsPercent, - minAmountPointsPercent: settings.minAmountPointsPercent, - revealJudgesAndBribes: settings.revealJudgesAndBribes, - revealTeams: settings.revealTeams, - showDiscordLink: settings.showDiscordLink, - revealLeaderboard: settings.revealLeaderboard, - revealMissions: settings.revealMissions, - allowJudging: settings.allowJudging, - disordLink: settings.disordLink, - }, - (err, newSettings) => { - if (err) { - reject(err); - } else { - resolve(newSettings); - } - }, - ); - } else { - resolve(result); - } - } - }); - }); + /** + * @description Initializes the scunt game settings + * @returns {Settings} + */ + async initScuntGameSettings() { + return ScuntGameSettingModel.findOneAndUpdate({}, {}, { upsert: true, new: true }).then( + (settings) => settings, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_SETTINGS', { cause: error }); + }, + ); }, + /** + * @description gets the scunt game settings + * @returns {Settings} + */ async getGameSettings() { - return new Promise((resolve, reject) => { - ScuntGameSettingModel.find({}, (err, settings) => { - if (err) { - reject(err); - } else if (!settings || settings === []) { - reject('ERROR'); - } else { - resolve(settings); // return game settings - } - }); - }); + return ScuntGameSettingModel.findOne().then( + (settings) => settings, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_SETTINGS', { cause: error }); + }, + ); }, + /** + * @description sets the scunt game settings + * @param {String} name + * @param {Number} amountOfTeams + * @param {Number} amountOfStarterBribePoints + * @param {Number} maxAmountPointsPercent + * @param {Number} minAmountPointsPercent + * @param {Boolean} revealJudgesAndBribes + * @param {Boolean} revealTeams + * @param {Boolean} showDiscordLink + * @param {String} discordLink + * @param {Boolean} revealLeaderboard + * @param {Boolean} revealMissions + * @param {Boolean} allowJudging + * @returns {Settings} + */ async setGameSettings( name, amountOfTeams, @@ -71,42 +58,36 @@ const ScuntGameSettingsServices = { revealMissions, allowJudging, ) { - return new Promise((resolve, reject) => { - ScuntGameSettingModel.findOneAndUpdate( - {}, - { - $set: { - name, - amountOfTeams, - amountOfStarterBribePoints, - maxAmountPointsPercent, - minAmountPointsPercent, - revealJudgesAndBribes, - revealTeams, - showDiscordLink, - discordLink, - revealLeaderboard, - revealMissions, - allowJudging, - }, - }, - { returnDocument: 'after' }, - function (err, settings) { - if (err) { - reject(err); - } else if (!settings) { - reject('ERROR'); - } else { - console.log('Updated settings!'); - ScuntSettingsSubscription.add(settings); - resolve(settings); - } + return ScuntGameSettingModel.findOneAndUpdate( + {}, + { + $set: { + name, + amountOfTeams, + amountOfStarterBribePoints, + maxAmountPointsPercent, + minAmountPointsPercent, + revealJudgesAndBribes, + revealTeams, + showDiscordLink, + discordLink, + revealLeaderboard, + revealMissions, + allowJudging, }, - ); - }); + }, + { returnDocument: 'after' }, + ).then( + (settings) => { + if (!settings) throw new Error('SETTINGS_NOT_FOUND'); + ScuntSettingsSubscription.add(settings); + return settings; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_SCUNT_SETTINGS', { cause: error }); + }, + ); }, }; module.exports = ScuntGameSettingsServices; - -/* eslint-enable no-unused-vars */ diff --git a/server/src/services/ScuntMissionServices.js b/server/src/services/ScuntMissionServices.js index 577ac49a..c58a03f0 100644 --- a/server/src/services/ScuntMissionServices.js +++ b/server/src/services/ScuntMissionServices.js @@ -2,157 +2,151 @@ const ScuntMissionModel = require('../models/ScuntMissionModel'); const ScuntGameSettingsModel = require('../models/ScuntGameSettingsModel'); const ScuntMissionServices = { + /** + * @description Gets all the scunt missions + * @param {Boolean} showHidden + * @param {User} user + * @returns {ScuntMission[]} + */ async getAllScuntMissions(showHidden, user) { - return new Promise((resolve, reject) => { - ScuntGameSettingsModel.findOne({}, {}, {}, (err1, settings) => { - if (err1) { - reject(err1); - } else if ( + await ScuntGameSettingsModel.findOne().then( + (settings) => { + if ( + // if settings is null or revealMissions is false and user does not have the required auth scope !settings || (!settings.revealMissions && !user.authScopes.approved.includes('scunt:exec show missions')) - ) { - reject('INVALID_SETTINGS'); - } else { - ScuntMissionModel.find(showHidden ? {} : { isHidden: false }) // finds documents with isHidden property set to false - .sort({ number: 1 }) // sort by number in ascending order (1) - .exec(function (err2, missions) { - // executes query --> callback - if (err2) { - // if error occurs while executing, reject --> result is null - reject(err2); - } else { - // else error = null, and result is populated with missions - resolve(missions); - } - }); - } - }); - }); + ) + throw new Error('INVALID_SETTINGS'); + // finds documents with isHidden property set to false + }, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_SETTINGS', { cause: error }); + }, + ); + return ScuntMissionModel.find( + showHidden ? {} : { isHidden: false }, + {}, + { + sort: { + number: 1, //Sort by Date Added DESC + }, + }, + ).then( + (results) => { + if (!results.length) throw new Error('NO_MISSIONS_FOUND'); + return results; + }, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_MISSIONS', { cause: error }); + }, + ); }, - async createMission(number, name, category, points, isHidden, isJudgingStation) { - return new Promise((resolve, reject) => { - ScuntMissionModel.create( - { number, name, category, points, isHidden, isJudgingStation }, - (err, mission) => { - if (err) { - reject(err); - } else { - resolve(mission); - } - }, - ); - }); + /** + * @description Creates a scunt mission + * @param {Number} number + * @param {String} name + * @param {String} category + * @param {Number} points + * @param {Boolean} isHidden + * @param {Boolean} isJudgingStation + * @returns {ScuntMission} + */ + async create(number, name, category, points, isHidden, isJudgingStation) { + return ScuntMissionModel.create({ + number, + name, + category, + points, + isHidden, + isJudgingStation, + }).then( + (mission) => mission, + (error) => { + throw new Error('UNABLE_TO_CREATE_MISSION', { cause: error }); + }, + ); }, + /** + * @description Create missions from a csv string. NOTE REMOVES ALL OTHER MISSIONS + * @param {String} csvString + * @returns {ScuntMission[]} + */ async createMultipleMissions(array) { - return new Promise((resolve, reject) => { - ScuntMissionModel.remove({}, (err1) => { - if (err1) { - reject(err1); - } - - ScuntMissionModel.create(array, {}, (err2, result) => { - if (err2) { - reject(err2); - } - resolve(result); - }); - }); - }); + return ScuntMissionModel.deleteMany({}).then( + () => { + return ScuntMissionModel.create(array).then( + (result) => result, + (error) => { + throw new Error('UNABLE_TO_CREATE_SCUNT_MISSIONS', { cause: error }); + }, + ); + }, + (error) => { + throw new Error('UNABLE_TO_CREATE_SCUNT_MISSIONS', { cause: error }); + }, + ); }, + /** + * @description Deletes a scunt mission + * @param {String} number + * @returns {ScuntMission} + */ async deleteMission(number) { - return new Promise((resolve, reject) => { - ScuntMissionModel.findOneAndDelete({ number }, (err, mission) => { - if (err || !mission) { - reject('UNABLE_TO_DELETE_MISSION'); - } else { - resolve(mission); - } - }); - }); + return ScuntMissionModel.findOneAndDelete({ number }).then( + (mission) => { + if (!mission) throw new Error('MISSION_NOT_FOUND'); + return mission; + }, + (error) => { + throw new Error('UNABLE_TO_DELETE_MISSION', { cause: error }); + }, + ); }, + /** + * @description Updates a scunt mission + * @param {Number} startMissionNumber + * @param {Number} endMissionNumber + * @param {Boolean} isHidden + * @param {Boolean} isJudgingStation + * @returns {ScuntMission[]} + */ async updateMissionVisibility(startMissionNumber, endMissionNumber, isHidden, isJudgingStation) { - return new Promise((resolve, reject) => { - ScuntMissionModel.updateMany( - { number: { $gte: startMissionNumber, $lte: endMissionNumber } }, - { $set: { isHidden, isJudgingStation } }, - { strictQuery: false }, - (err, result) => { - if (err) { - reject(err); - } else if (!result) { - reject('INTERNAL_ERROR'); - } else { - resolve(result); - } - }, - ); - }); + return ScuntMissionModel.updateMany( + { number: { $gte: startMissionNumber, $lte: endMissionNumber } }, + { $set: { isHidden, isJudgingStation } }, + { strictQuery: false }, + ).then( + (missions) => { + if (missions.modifiedCount === 0) throw new Error('NO_MISSIONS_FOUND'); + return missions; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_MISSION_VISIBILITY', { cause: error }); + }, + ); }, + /** + * @description Gets a scunt mission + * @param {Number} number + * @returns {ScuntMission} + */ async getMission(number) { - return new Promise((resolve, reject) => { - ScuntMissionModel.findOne({ number }, {}, {}, (err, mission) => { - if (err) { - reject(err); - } else if (!mission || mission.isHidden) { - reject('MISSION_DOES_NOT_EXIST'); - } else { - resolve(mission); - } - }); - }); + return ScuntMissionModel.findOne({ number }).then( + (mission) => { + if (!mission || mission.isHidden) throw new Error('MISSION_NOT_FOUND'); + return mission; + }, + (error) => { + throw new Error('UNABLE_TO_GET_MISSION', { cause: error }); + }, + ); }, }; -const parseCsvString = (csvString, mapping, delimiter = ',') => { - // regex checks for delimiters that are not contained within quotation marks - const regex = new RegExp(`(?!\\B"[^"]*)${delimiter}(?![^"]*"\\B)`); - if (csvString.length === 0 || !/\r\b|\r|\n/.test(csvString)) { - return { data: [] }; - } - const rows = csvString.split(/\r\n|\r|\n/).filter((elem) => elem !== ''); - const headers = rows[0].split(regex).map((h) => h.replace(/^(["'])(.*)\1$/, '$2')); - const requiredHeaders = Object.keys(mapping).filter((m) => mapping[m].required); - const headerErrors = []; - requiredHeaders.forEach((header) => { - if (!headers.includes(header)) { - headerErrors.push({ row: 1, column: header, errorMessage: `Missing header ${header}` }); - } - }); - if (headerErrors.length > 0) { - return { data: [], errors: headerErrors }; - } - const allowedHeaders = Object.keys(mapping); - const dataRows = rows.slice(1); - const { data, errors } = dataRows.reduce( - (previous, row, rowIndex) => { - const values = row.split(regex); - const parsedRow = headers.reduce((previousObj, current, index) => { - if (allowedHeaders.includes(current)) { - const val = mapping[current].parseFunction(values[index].replace(/^(["'])(.*)\1$/, '$2')); // removes any surrounding quotation marks - if (mapping[current].validator(val)) { - previousObj[mapping[current].key] = val; - } else { - previous.errors.push({ - row: rowIndex + 2, - column: current, - errorMessage: mapping[current].errorMessage, - }); - } - } - return previousObj; - }, {}); - previous.data.push(parsedRow); - return previous; - }, - { data: [], errors: [] }, - ); - return { data, errors }; -}; - module.exports = ScuntMissionServices; diff --git a/server/src/services/ScuntTeamServices.js b/server/src/services/ScuntTeamServices.js index c512002c..ef314306 100644 --- a/server/src/services/ScuntTeamServices.js +++ b/server/src/services/ScuntTeamServices.js @@ -1,5 +1,3 @@ -/* eslint-disable no-unused-vars */ - const ScuntTeamModel = require('../models/ScuntTeamModel'); const LeadurModel = require('../models/LeadurModel'); const ScuntGameSettingsModel = require('../models/ScuntGameSettingsModel'); @@ -8,304 +6,355 @@ const LeaderboardSubscription = require('../subscribers/leaderboardSubscriber'); const mongoose = require('mongoose'); const ScuntTeamServices = { + /** + * @description Updates a Leedurs team + * @param {String} userId + * @param {Number} teamNumber + * @returns {Leadur} + */ async updateLeaderTeam(userId, teamNumber) { - return new Promise((resolve, reject) => { - LeadurModel.findOneAndUpdate( - { _id: userId }, - { scuntTeam: teamNumber }, - { returnDocument: 'after' }, - (err, Leadur) => { - if (err || !Leadur) { - reject('UNABLE_TO_UPDATE_LEADER'); - } else { - resolve(Leadur); - } - }, - ); - }); + return LeadurModel.findByIdAndUpdate( + userId, + { scuntTeam: teamNumber }, + { returnDocument: 'after' }, + ).then( + (leadur) => { + if (!leadur) throw new Error('LEADUR_NOT_FOUND'); + return leadur; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_LEADER', { cause: error }); + }, + ); }, + /** + * @description Gets team points + * @returns {ScuntTeam[]} + */ async getTeamPoints() { //Get amount of teams (Scunt Game Settings) and points for each team //Add up and calculate all tranactions for each team - return new Promise((resolve, reject) => { - ScuntTeamModel.find({}, { name: 1, number: 1, points: 1 }, {}, (err, teams) => { - if (err) { - reject(err); - } else if (!teams) { - reject('UNABLE_TO_GET_TEAM_POINTS'); - } else { - resolve(teams); - } - }); - }); + return ScuntTeamModel.find({}, { name: 1, number: 1, points: 1 }).then( + (teams) => { + if (!teams.length) throw new Error('TEAMS_NOT_FOUND'); + return teams; + }, + (error) => { + throw new Error('UNABLE_TO_GET_TEAM_POINTS', { cause: error }); + }, + ); }, + /** + * @description Gets teams + * @returns {ScuntTeam[]} + */ async getTeams() { - return new Promise((resolve, reject) => { - ScuntTeamModel.find({}, { name: 1 }, {}, (err, teams) => { - if (err) { - reject(err); - } else if (!teams) { - reject('UNABLE_TO_GET_TEAMS'); - } else { - resolve(teams); - } - }); - }); + return ScuntTeamModel.find({}, { name: 1, number: 1 }).then( + (teams) => { + if (!teams.length) throw new Error('TEAMS_NOT_FOUND'); + return teams; + }, + (error) => { + throw new Error('UNABLE_TO_GET_TEAMS', { cause: error }); + }, + ); }, async calculatePoints(teamNumber, totalPoints) { - const teams = ScuntTeamModel.find({}, { name: 1, number: 1, points: 1 }, {}).sort({ - points: -1, - }); + try { + const teams = await ScuntTeamModel.find( + {}, + { name: 1, number: 1, points: 1 }, + { sort: { points: -1 } }, + ); - const teamPosition = teams.map((t, pos) => { - if (teamNumber === t.number) { - return pos + 1; - } - }); + // finds the rank of the team (i.e., index in teams array) + const teamPosition = teams?.findIndex((t) => teamNumber === t.number) + 1; - return (teamPosition / teams.length) * totalPoints; + return (teamPosition / teams.length) * totalPoints; + } catch (error) { + throw new Error('UNABLE_TO_CALCULATE_POINTS', { cause: error }); + } }, + /** + * @description Adds bribe points to a team + * @param {Number} teamNumber + * @param {Number} points + * @param {User} user + * @returns {ScuntTeam , Leadur} + */ async bribeTransaction(teamNumber, points, user) { const curvedPoints = await this.calculatePoints(teamNumber, points); + if (!user.scuntJudgeBribePoints || curvedPoints > user.scuntJudgeBribePoints) + throw new Error('NOT_ENOUGH_BRIBE_POINTS'); - return new Promise((resolve, reject) => { - if (!user.scuntJudgeBribePoints || curvedPoints > user.scuntJudgeBribePoints) { - reject('NOT_ENOUGH_BRIBE_POINTS'); - } else { - ScuntGameSettingsModel.findOne({}, (err, settings) => { - if (err) { - reject(err); - } else if (!settings || !settings.allowJudging) { - reject('INVALID_SETTINGS'); - } else { - LeadurModel.findByIdAndUpdate( - user.id, - { $set: { scuntJudgeBribePoints: user.scuntJudgeBribePoints - curvedPoints } }, - { upsert: false, returnDocument: 'after' }, - (err, leadur) => { - if (err) { - reject(err); - } else if (!leadur) { - reject('INTERNAL_ERROR'); - } else { - ScuntTeamModel.findOneAndUpdate( - { number: teamNumber }, - { - $inc: { curvedPoints }, - $push: { - transactions: [ - { - name: `${curvedPoints.toString()} points bribe from ${user.firstName} ${ - user.lastName - }`, - curvedPoints, - }, - ], - }, - }, - { upsert: false, returnDocument: 'after' }, - (err, team) => { - if (err) { - reject(err); - } else if (!team) { - reject('INVALID_TEAM_NUMBER'); - } else { - LeaderboardSubscription.add({ team: team.number, score: team.points }); - resolve({ team, leadur }); - } - }, - ); - } - }, - ); - } - }); - } - // Need to get remaining bribe points of the judge user; - }); - }, + await ScuntGameSettingsModel.findOne({}).then( + (settings) => { + if (!settings) throw new Error('INVALID_SETTINGS'); + if (!settings.allowJudging) throw new Error('NOT_ALLOWED_TO_JUDGE'); + }, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_SETTINGS', { cause: error }); + }, + ); - async getScuntJudges() { - return new Promise((resolve, reject) => { - LeadurModel.find( - { - $or: [ - { 'authScopes.approved': 'scunt:judge bribe points' }, - { 'authScopes.approved': 'scunt:judge missions' }, + const leadur = await LeadurModel.findByIdAndUpdate( + user.id, + { $set: { scuntJudgeBribePoints: user.scuntJudgeBribePoints - curvedPoints } }, + { upsert: false, returnDocument: 'after' }, + ).then( + (leadur) => { + if (!leadur) throw new Error('LEADUR_NOT_FOUND'); + return leadur; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_LEADUR', { cause: error }); + }, + ); + + return ScuntTeamModel.findOneAndUpdate( + { number: teamNumber }, + { + $inc: { points: curvedPoints }, + $push: { + transactions: [ + { + name: `${points.toString()} points bribe from ${user.firstName} ${user.lastName}`, + points: curvedPoints, + }, ], }, - (err, judgeUsers) => { - if (err) { - reject(err); - } else { - resolve(judgeUsers); - } - }, - ); - }); + }, + { upsert: false, returnDocument: 'after' }, + ).then( + (team) => { + if (!team) { + leadur.set({ scuntJudgeBribePoints: user.scuntJudgeBribePoints }); + leadur.save(); + throw new Error('INVALID_TEAM_NUMBER'); + } + LeaderboardSubscription.add({ team: team.number, score: team.points }); + return { team, leadur }; + }, + (error) => { + leadur.set({ scuntJudgeBribePoints: user.scuntJudgeBribePoints }); + leadur.save(); + throw new Error('UNABLE_TO_UPDATE_TEAM', { cause: error }); + }, + ); }, + /** + * @description Gets all scunt judges + * @returns {Leadur[]} + */ + async getScuntJudges() { + return LeadurModel.find({ + $or: [ + { 'authScopes.approved': 'scunt:judge bribe points' }, + { 'authScopes.approved': 'scunt:judge missions' }, + ], + }).then( + (judgeUsers) => { + if (!judgeUsers.length) throw new Error('JUDGES_NOT_FOUND'); + return judgeUsers; + }, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_JUDGES', { cause: error }); + }, + ); + }, + + /** + * @description Change a judge's bribe points + * @param {String} judgeUserId + * @param {Number} points + * @param {Boolean} isAddPoints + * @returns {Leadur} + */ async refillBribePoints(judgeUserId, points, isAddPoints) { - return new Promise((resolve, reject) => { - LeadurModel.findByIdAndUpdate( - judgeUserId, - isAddPoints - ? { $inc: { scuntJudgeBribePoints: points } } - : { $set: { scuntJudgeBribePoints: points } }, - { upsert: false, returnDocument: 'after' }, - (err, leadur) => { - if (err) { - reject(err); - } else if (!leadur) { - reject('INVALID_LEADUR_ID'); - } else { - resolve(leadur); - } - }, - ); - }); + return LeadurModel.findByIdAndUpdate( + judgeUserId, + isAddPoints + ? { $inc: { scuntJudgeBribePoints: points } } + : { $set: { scuntJudgeBribePoints: points } }, + { upsert: false, returnDocument: 'after' }, + ).then( + (leadur) => { + if (!leadur) throw new Error('LEADUR_NOT_FOUND'); + return leadur; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_LEADUR', { cause: error }); + }, + ); }, + /** + * @description Adds a transaction + * @param {Number} teamNumber + * @param {Number} missionNumber + * @param {Number} points + * @returns {String} + */ async addTransaction(teamNumber, missionNumber, points) { const curvedPoints = await this.calculatePoints(teamNumber, points); + // check if judging is allowed + await ScuntGameSettingsModel.findOne({}).then( + (settings) => { + if (!settings) throw new Error('INVALID_SETTINGS'); + if (!settings.allowJudging) throw new Error('NOT_ALLOWED_TO_JUDGE'); + }, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_SETTINGS', { cause: error }); + }, + ); - return new Promise((resolve, reject) => { - //TODO look up mission to get amount of points - ScuntGameSettingsModel.findOne({}, (err, settings) => { - if (err) { - reject(err); - } else if (!settings || !settings.allowJudging) { - reject('INVALID_SETTINGS'); - } else { - //Compare with maxAmountPointsPercent and minAmountPointsPercent to ensure within bounds set by game rules - ScuntTeamModel.findOne({ number: teamNumber }, (err, team) => { - if (err) { - reject(err); - } else { - const prevPoints = team.transactions.reduce((prev, curr) => { - if (curr.missionNumber === missionNumber && curr.points > prev) { - prev = curr.points; - } - return prev; - }, 0); - if (prevPoints < curvedPoints) { - team.points += curvedPoints - prevPoints; - } - const name = - (!prevPoints ? 'Added ' : prevPoints < curvedPoints ? 'Updated to ' : '') + - curvedPoints.toString() + - ' points for mission #' + - missionNumber.toString() + - ' for team ' + - teamNumber.toString(); - team.transactions.push({ name, missionNumber, points: curvedPoints }); - team.save((err, res) => { - if (err) { - reject(err); - } else { - LeaderboardSubscription.add({ team: res.number, score: res.points }); - resolve(name); - } - }); - } - }); - } - }); + // check if team exists + const team = await ScuntTeamModel.findOne({ number: teamNumber }).then( + (team) => { + if (!team) throw new Error('INVALID_TEAM_NUMBER'); + return team; + }, + (error) => { + throw new Error('UNABLE_TO_GET_TEAM', { cause: error }); + }, + ); - // Get max and min possible points by multiplying missionNumber's mission by minAmountPointsPercent and maxAmountPointsPercent from game settings - return true; - }); + // check if team has already been judged for this mission + const prevPoints = team.transactions.reduce((prev, curr) => { + if (curr.missionNumber === missionNumber && curr.points > prev) { + prev = curr.points; + } + return prev; + }, 0); + if (prevPoints < curvedPoints) { + team.points += curvedPoints - prevPoints; + } + + // add transaction to team + const transaction = + (!prevPoints ? 'Added ' : prevPoints < curvedPoints ? 'Updated to ' : '') + + points.toString() + + ' points for mission #' + + missionNumber.toString() + + ' for team ' + + teamNumber.toString(); + team.transactions.push({ name: transaction, missionNumber, points: curvedPoints }); + + return team.save().then( + (team) => { + LeaderboardSubscription.add({ team: team.number, score: team.points }); + return transaction; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_TEAM', { cause: error }); + }, + ); }, + /** + * @description Subtracts points from a team + * @param {Number} teamNumber + * @param {Number} points + * @returns {ScuntTeam} + */ async subtractTransaction(teamNumber, points) { - return new Promise((resolve, reject) => { - ScuntGameSettingsModel.findOne({}, (err, settings) => { - if (err) { - reject(err); - } else if (!settings || !settings.allowJudging) { - reject('INVALID_SETTINGS'); - } else { - ScuntTeamModel.findOneAndUpdate( - { number: teamNumber }, + // check if judging is allowed + await ScuntGameSettingsModel.findOne({}).then( + (settings) => { + if (!settings) throw new Error('INVALID_SETTINGS'); + if (!settings.allowJudging) throw new Error('NOT_ALLOWED_TO_JUDGE'); + }, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_SETTINGS', { cause: error }); + }, + ); + // check if team exists and subtract points + return ScuntTeamModel.findOneAndUpdate( + { number: teamNumber }, + { + $inc: { points: Math.abs(points) * -1 }, + $push: { + transactions: [ { - $inc: { points: Math.abs(points) * -1 }, - $push: { - transactions: [ - { - name: 'Subtracted ' + points.toString() + ' from team ' + teamNumber.toString(), - points: Math.abs(points) * -1, - }, - ], - }, + name: 'Subtracted ' + points.toString() + ' from team ' + teamNumber.toString(), + points: Math.abs(points) * -1, }, - { upsert: false, returnDocument: 'after' }, - (err, team) => { - if (err) { - reject(err); - } else if (!team) { - reject('INVALID_TEAM_NAME'); - } else { - LeaderboardSubscription.add({ team: team.number, score: team.points }); - resolve(team); - } - }, - ); - } - }); - }); + ], + }, + }, + { upsert: false, returnDocument: 'after' }, + ).then( + (team) => { + if (!team) throw new Error('INVALID_TEAM_NUMBER'); + LeaderboardSubscription.add({ team: team.number, score: team.points }); + return team; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_TEAM', { cause: error }); + }, + ); }, + /** + * @description Gets a team's transactions + * @param {Number} teamNumber + * @returns {ScuntTeam} + */ async viewTransactions(teamNumber) { - return new Promise((resolve, reject) => { - ScuntTeamModel.findOne({ number: teamNumber }, {}, {}, (err, teams) => { - if (err) { - reject(err); - } else if (!teams) { - reject('UNABLE_TO_GET_TEAM_INFO'); - } else { - resolve(teams); - } - }); - }); + return ScuntTeamModel.findOne({ number: teamNumber }).then( + (team) => { + if (!team) throw new Error('INVALID_TEAM_NUMBER'); + return team.transactions; + }, + (error) => { + throw new Error('UNABLE_TO_GET_TRANSACTIONS', { cause: error }); + }, + ); }, + /** + * @description Gets a team's transactions + * @param {Number} teamNumber + * @param {Number} missionNumber + * @returns {Number} + */ async checkTransaction(teamNumber, missionNumber) { - return new Promise((resolve, reject) => { - ScuntTeamModel.findOne( - { number: teamNumber }, - { - transactions: { - $filter: { - input: '$transactions', - as: 'transaction', - cond: { $eq: ['$$transaction.missionNumber', missionNumber] }, - }, + return ScuntTeamModel.findOne( + { number: teamNumber }, + { + transactions: { + $filter: { + input: '$transactions', + as: 'transaction', + cond: { $eq: ['$$transaction.missionNumber', missionNumber] }, }, }, - {}, - (err, team) => { - if (err) { - reject(err); - } else if (!team) { - reject('INVALID_TEAM'); - } else { - resolve( - team.transactions.reduce((prev, curr) => { - if (curr.points > prev) { - prev = curr.points; - } - return prev; - }, 0), - ); + }, + ).then( + (team) => { + if (!team) throw new Error('INVALID_TEAM_NUMBER'); + return team.transactions.reduce((prev, curr) => { + if (curr.points > prev) { + prev = curr.points; } - }, - ); - }); + return prev; + }, 0); + }, + (error) => { + throw new Error('UNABLE_TO_GET_TRANSACTIONS', { cause: error }); + }, + ); }, + + /** + * @description Initializes teams + * @returns {ScuntTeam[]} + */ async initializeTeams() { /* General approach is to: @@ -313,199 +362,228 @@ const ScuntTeamServices = { 2. Create the correct number of teams and upsert them into mongo 3. Assign each frosh to a team based off their froshGroup, discipline, and pronouns */ - return new Promise((resolve, reject) => { - ScuntGameSettingsModel.findOne({}, {}, {}, async (err, settings) => { - if (err) { - reject(err); - } else if (!settings || !settings.amountOfTeams) { - reject('INVALID_OR_MISSING_SCUNT_SETTINGS'); - } else { - const numTeams = settings.amountOfTeams; - const teams = []; - for (let i = 1; i <= numTeams; i++) { - teams.push({ - number: i, - name: `Team ${i}`, - froshGroups: {}, - pronouns: {}, - disciplines: {}, - count: 0, - }); + // get the number of teams from the scunt game settings + const numTeams = await ScuntGameSettingsModel.findOne({}).then( + (settings) => { + if (!settings) throw new Error('INVALID_SETTINGS'); + if (!settings.amountOfTeams) throw new Error('MISSING_SCUNT_SETTINGS'); + return settings.amountOfTeams; + }, + (error) => { + throw new Error('UNABLE_TO_GET_SCUNT_SETTINGS', { cause: error }); + }, + ); + + // create an array of teams to upsert + const teams = [...Array(numTeams).keys()].map((i) => ({ + updateOne: { + filter: { + number: i + 1, + }, + update: { + $set: { + number: i + 1, + name: `Team ${i + 1}`, + points: 0, + transactions: [], + }, + }, + upsert: true, + }, + })); + + const scuntTeamsStats = [...Array(numTeams)].map((_, index) => ({ + number: index + 1, + name: `Team ${index + 1}`, + froshGroups: {}, + pronouns: {}, + disciplines: {}, + count: 0, + })); + + await ScuntTeamModel.collection.drop(); + + // upsert the teams + await ScuntTeamModel.collection.bulkWrite(teams).then( + (result) => { + if (result.upsertedCount !== numTeams) throw new Error('TEAM_COUNT_MISMATCH'); + }, + (error) => { + throw new Error('UNABLE_TO_CREATE_TEAMS', { cause: error }); + }, + ); + + // get all the frosh who signed up for scunt + const scuntFrosh = await FroshModel.find({ attendingScunt: true }).then( + (allFroshList) => { + if (!allFroshList.length) throw new Error('SCUNT_FROSH_NOT_FOUND'); + return allFroshList; + }, + (error) => { + throw new Error('UNABLE_TO_GET_ALL_FROSH', { cause: error }); + }, + ); + + const scuntTeamDict = {}; + + // create an array of promises to save the updated frosh + return Promise.all( + scuntFrosh.map(async (currFrosh) => { + if (currFrosh.scuntPreferredMembers.length) { + let isMatch = true; + for (let i = 0; i < currFrosh.scuntPreferredMembers.length; i++) { + if (currFrosh.scuntPreferredMembers[i] != currFrosh.email) { + const preferredTeamMember = scuntFrosh.filter( + (frosh) => frosh.email == currFrosh.scuntPreferredMembers[i], + )[0]; + + if (!preferredTeamMember) { + isMatch = false; + break; + } + + if ( + !currFrosh.scuntPreferredMembers.every((val) => + preferredTeamMember.scuntPreferredMembers.includes(val), + ) + ) { + isMatch = false; + break; + } + } } - // upsert the scunt teams - ScuntTeamModel.collection.bulkWrite( - teams.map((t) => ({ - updateOne: { - filter: { - number: t.number, - }, - update: { - $set: { - number: t.number, - name: t.name, - points: 0, - transactions: [], - }, - }, - upsert: true, - }, - })), - {}, - (err) => { - if (err) { - reject(err); - } else { - FroshModel.find({ scunt: true }, {}, {}, (err, frosh) => { - if (err) { - reject(err); - } else { - const scuntTeamDict = {}; - // create an array of promises to save the updated frosh - const updates = frosh.map((f) => { - if (f.scuntPreferredMembers.length) { - let isMatch = true; - for (let i = 0; i < f.scuntPreferredMembers.length; i++) { - if (f.scuntPreferredMembers[i] !== f.email) { - FroshModel.find({ email: f.scuntPreferredMembers[i] }, (err, frosh) => { - if (err) { - reject(err); - } else { - // there should only be one user with a particular email so map is not needed - const sortedFPreferred = f.scuntPreferredMembers.sort(); - const sortedFroshPreferred = frosh[0].scuntPreferredMembers.sort(); - if (sortedFPreferred !== sortedFroshPreferred) { - isMatch = false; - } - } - }); - if (!isMatch) { - break; - } - } - } - - if (isMatch) { - let teamIndex = -1; - for (let i = 0; i < f.scuntPreferredMembers.length; i++) { - if (f.scuntPreferredMembers[i] !== f.email) { - if (scuntTeamDict[f.scuntPreferredMembers[i]] !== undefined) { - teamIndex = scuntTeamDict[f.scuntPreferredMembers[i]]; - break; - } - } - } - - if (teamIndex === -1) { - let minCount = 100000; - for (let i = 0; i < teams.length; i++) { - if (teams[i].count === 0) { - teamIndex = i; - break; - } - if (teams[i].count < minCount) { - minCount = teams[i].count; - teamIndex = i; - } - } - } - - const team = teams[teamIndex]; - f.scuntTeam = team.number; - scuntTeamDict[f.email] = teamIndex; - team.froshGroups[f.froshGroup] = - (team.froshGroups[f.froshGroup] ?? 0) + 1; - team.pronouns[f.pronouns] = (team.pronouns[f.pronouns] ?? 0) + 1; - team.disciplines[f.discipline] = - (team.disciplines[f.discipline] ?? 0) + 1; - team.count += 1; - return f.save({ validateModifiedOnly: true }); - } - } - let minScore = 100000; - let teamIndex = -1; - for (let i = 0; i < teams.length; i++) { - const score = - 0.5 * (teams[i].froshGroups[f.froshGroup] ?? 0) + - 0.5 * (teams[i].pronouns[f.pronouns] ?? 0) + - 0.5 * (teams[i].disciplines[f.discipline] ?? 0) + - teams[i].count; - - if (score < minScore) { - minScore = score; - teamIndex = i; - } - } - const team = teams[teamIndex]; - f.scuntTeam = team.number; - team.froshGroups[f.froshGroup] = (team.froshGroups[f.froshGroup] ?? 0) + 1; - team.pronouns[f.pronouns] = (team.pronouns[f.pronouns] ?? 0) + 1; - team.disciplines[f.discipline] = (team.disciplines[f.discipline] ?? 0) + 1; - team.count += 1; - return f.save({ validateModifiedOnly: true }); - }); - // await the resolution of the full array, and then resolve only if every frosh saved successfully - Promise.all(updates) - .then(() => resolve(teams)) - .catch(() => reject('INTERNAL_ERROR')); - } - }); + + if (isMatch) { + let teamIndex = -1; + for (let i = 0; i < currFrosh.scuntPreferredMembers.length; i++) { + if (currFrosh.scuntPreferredMembers[i] !== currFrosh.email) { + if (scuntTeamDict[currFrosh.scuntPreferredMembers[i]] !== undefined) { + teamIndex = scuntTeamDict[currFrosh.scuntPreferredMembers[i]]; + break; + } } - }, - ); + } + + if (teamIndex === -1) { + let minCount = 100000; + for (let i = 0; i < scuntTeamsStats.length; i++) { + if (scuntTeamsStats[i].count === 0) { + teamIndex = i; + break; + } + if (scuntTeamsStats[i].count < minCount) { + minCount = scuntTeamsStats[i].count; + teamIndex = i; + } + } + } + + const team = scuntTeamsStats[teamIndex]; + currFrosh.scuntTeam = team.number; + scuntTeamDict[currFrosh.email] = teamIndex; + team.froshGroups[currFrosh.froshGroup] = + (team.froshGroups[currFrosh.froshGroup] ?? 0) + 1; + team.pronouns[currFrosh.pronouns] = (team.pronouns[currFrosh.pronouns] ?? 0) + 1; + team.disciplines[currFrosh.discipline] = + (team.disciplines[currFrosh.discipline] ?? 0) + 1; + team.count += 1; + return await currFrosh.save({ validateModifiedOnly: true }); + } } - }); - }); + let minScore = 100000; + let teamIndex = -1; + for (let i = 0; i < scuntTeamsStats.length; i++) { + const score = + 0.5 * (scuntTeamsStats[i].froshGroups[currFrosh.froshGroup] ?? 0) + + 0.5 * (scuntTeamsStats[i].pronouns[currFrosh.pronouns] ?? 0) + + 0.5 * (scuntTeamsStats[i].disciplines[currFrosh.discipline] ?? 0) + + scuntTeamsStats[i].count; + + if (score < minScore) { + minScore = score; + teamIndex = i; + } + } + const team = scuntTeamsStats[teamIndex]; + currFrosh.scuntTeam = team.number; + team.froshGroups[currFrosh.froshGroup] = (team.froshGroups[currFrosh.froshGroup] ?? 0) + 1; + team.pronouns[currFrosh.pronouns] = (team.pronouns[currFrosh.pronouns] ?? 0) + 1; + team.disciplines[currFrosh.discipline] = (team.disciplines[currFrosh.discipline] ?? 0) + 1; + team.count += 1; + return currFrosh.save({ validateModifiedOnly: true }).then( + (frosh) => frosh, + (error) => { + throw new Error('UNABLE_TO_UPDATE_FROSH', { cause: error }); + }, + ); + }), + ); }, + /** + * @description Deletes a transaction + * @param {Number} teamNumber + * @param {String} id + * @returns {ScuntTeam} + */ async deleteTransaction(teamNumber, id) { - return new Promise((resolve, reject) => { - ScuntTeamModel.findOneAndUpdate( - { number: teamNumber }, - { $pull: { transactions: { _id: { $in: [mongoose.Types.ObjectId(id)] } } } }, - { returnDocument: 'after' }, - (err, team) => { - if (err) { - reject(err); - } else if (!team) { - reject('INVALID_TEAM'); - } else { - resolve(true); - } - }, - ); - }); + return ScuntTeamModel.findOneAndUpdate( + { number: teamNumber }, + { $pull: { transactions: { _id: { $in: [new mongoose.Types.ObjectId(id)] } } } }, + { returnDocument: 'after' }, + ).then( + (team) => { + if (!team) throw new Error('TEAM_NOT_FOUND'); + return team; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_TEAM', { cause: error }); + }, + ); }, + + /** + * @description Gets recent transactions + * @returns {Transaction[]} + */ async viewRecentTransactions() { - return new Promise((resolve, reject) => { - ScuntTeamModel.aggregate([ - { $project: { transactions: 1, number: 1, name: 1 } }, - { $unwind: { path: '$transactions' } }, - { $sort: { createdAt: 1 } }, - { $limit: 50 }, - ]).exec((err, result) => { - if (err) { - reject(err); - } else { - resolve(result); - } - }); - }); + return ScuntTeamModel.aggregate([ + { $project: { transactions: 1, number: 1, name: 1 } }, + { $unwind: { path: '$transactions' } }, + { $sort: { createdAt: 1 } }, + { $limit: 50 }, + ]).then( + (transactions) => { + if (!transactions.length) throw new Error('TRANSACTIONS_NOT_FOUND'); + return transactions; + }, + (error) => { + throw new Error('UNABLE_TO_GET_TRANSACTIONS', { cause: error }); + }, + ); }, + + /** + * @description Updates a team's name + * @param {Number} teamNumber + * @param {String} rename + * @returns {ScuntTeam} + */ async setTeamName(teamNumber, rename) { - return new Promise((resolve, reject) => { - ScuntTeamModel.findOneAndUpdate({ number: teamNumber }, { name: rename }, (err, team) => { - if (err) { - reject(err); - } else if (!team) { - reject('INVALID_TEAM_NUMBER'); - } else { - resolve({ team }); - } - }); - }); + return ScuntTeamModel.findOneAndUpdate( + { number: teamNumber }, + { name: rename }, + { new: true, returnDocument: 'after' }, + ).then( + (team) => { + if (!team) throw new Error('INVALID_TEAM_NUMBER'); + return team; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_TEAM', { cause: error }); + }, + ); }, }; module.exports = ScuntTeamServices; - -/* eslint-enable no-unused-vars */ diff --git a/server/src/services/TimelineServices.js b/server/src/services/TimelineServices.js index 12cfa888..918f0483 100644 --- a/server/src/services/TimelineServices.js +++ b/server/src/services/TimelineServices.js @@ -1,61 +1,78 @@ const TimelineModel = require('../models/TimelineModel'); const TimelineServices = { - async getAllTimelines() { - return new Promise((resolve, reject) => { - TimelineModel.find({}) - .sort({ date: 1 }) - .exec(function (err, Timelines) { - if (err) { - reject(err); - } else { - resolve(Timelines); - } - }); - }); + /** + * @description Gets all the timeline elements + * @returns {Timeline[]} + */ + async getAll() { + return TimelineModel.find({}, null, { sort: { date: 1 } }).then( + (result) => result, + (error) => { + throw new Error('UNABLE_TO_GET_TIMELINE', { cause: error }); + }, + ); }, - async updateTimelineElement(id, date, eventName, description, link, linkLabel) { - return new Promise((resolve, reject) => { - TimelineModel.findOneAndUpdate( - { _id: id }, - { date, eventName, description, link, linkLabel }, - (err, Timeline) => { - if (err || !Timeline) { - reject('UNABLE_TO_UPDATE_TIMELiNE'); - } else { - resolve(Timeline); - } - }, - ); - }); + /** + * @description Updates a timeline element + * @param {String} id + * @param {Date} date + * @param {String} eventName + * @param {String} description + * @param {String} link + * @param {String} linkLabel + * @returns {Timeline} + */ + async update(id, date, eventName, description, link, linkLabel) { + return TimelineModel.findByIdAndUpdate( + id, + { date, eventName, description, link, linkLabel }, + { new: true, returnDocument: 'after' }, + ).then( + (result) => { + if (!result) throw new Error('TIMELINE_NOT_FOUND'); + return result; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_TIMELINE', { cause: error }); + }, + ); }, - async saveNewTimelineElement(date, eventName, description, link, linkLabel) { - return new Promise((resolve, reject) => { - TimelineModel.create( - { date, eventName, description, link, linkLabel }, - (err, newTimeline) => { - if (err) { - reject(err); - } else { - resolve(newTimeline); - } - }, - ); - }); + /** + * @description Creates a timeline element + * @param {Date} date + * @param {String} eventName + * @param {String} description + * @param {String} link + * @param {String} linkLabel + * @returns {Timeline} + */ + async create(date, eventName, description, link, linkLabel) { + return TimelineModel.create({ date, eventName, description, link, linkLabel }).then( + (result) => result, + (error) => { + throw new Error('UNABLE_TO_CREATE_TIMELINE', { cause: error }); + }, + ); }, - async deleteTimelineElement(id) { - return new Promise((resolve, reject) => { - TimelineModel.findOneAndDelete({ _id: id }, (err, deleteTimeline) => { - if (err || !deleteTimeline) { - reject('UNABLE_TO_DELETE_Timeline'); - } else { - resolve(deleteTimeline); - } - }); - }); + /** + * @description Deletes a timeline element + * @param {String} id timeline element id + * @returns {Timeline} + */ + async delete(id) { + return TimelineModel.findByIdAndDelete(id).then( + (result) => { + if (!result) throw new Error('TIMELINE_NOT_FOUND'); + return result; + }, + (error) => { + throw new Error('UNABLE_TO_DELETE_TIMELINE', { cause: error }); + }, + ); }, }; diff --git a/server/src/services/UserServices.js b/server/src/services/UserServices.js index 13133c03..3c3e96be 100644 --- a/server/src/services/UserServices.js +++ b/server/src/services/UserServices.js @@ -16,6 +16,15 @@ function createScuntToken() { return result; } +/** + * @description Creates an email confirmation token for a user + * @param {string} email + * @returns {Token} + */ +function generateEmailConfirmationToken(email) { + return jwt.sign(email, process.env.JWT_EMAIL_CONFIRMATION_TOKEN); +} + const UserServices = { /** * Validates the fields for a user. @@ -47,54 +56,63 @@ const UserServices = { * @param {String} preferredName * @return {Promise} */ - async createUser(email, password, firstName, lastName, preferredName) { + async create(email, password, firstName, lastName, preferredName) { const scuntToken = createScuntToken(); + const hashedPassword = await bcrypt.hash(password, 10).then( + (hash) => hash, + (error) => { + throw new Error('UNABLE_TO_HASH_PASSWORD', { cause: error }); + }, + ); - return new Promise((resolve, reject) => { - bcrypt - .hash(password, 10) - .then((hashedPassword) => { - UserModel.create( - { email, hashedPassword, firstName, lastName, preferredName, scuntToken }, - (err, newUser) => { - if (err) { - reject(err); - } else { - emailConfirmationSubscription.add(newUser); - resolve(newUser); - } - }, - ); - }) - .catch((err) => { - reject(err); - }); - }); + return UserModel.create({ + email, + hashedPassword, + firstName, + lastName, + preferredName, + scuntToken, + }).then( + (newUser) => { + const token = generateEmailConfirmationToken(email); + emailConfirmationSubscription.add({ token, email }); + return newUser; + }, + (error) => { + throw new Error('UNABLE_TO_CREATE_USER', { cause: error }); + }, + ); }, + /** + * @description Creates a password reset token for a user + * @param {string} email + * @returns {Token} + */ async generatePasswordResetToken(email) { + const userEmail = await UserModel.findOne({ email }).then( + (user) => { + if (!user) throw new Error('USER_NOT_FOUND'); + return email; + }, + (error) => { + throw new Error('UNABLE_TO_GET_USER', { cause: error }); + }, + ); return new Promise((resolve, reject) => { - UserModel.findOne({ email }, (err, user) => { - if (err) { - reject(err); - } else if (!user) { - reject('INVALID_EMAIL'); - } else { - const { email } = user; - jwt.sign( - { email, timestamp: Date.now() }, - process.env.JWT_RESET_TOKEN, - { expiresIn: '7d' }, - (err, token) => { - if (err) { - reject(err); - } else { - resolve(token); - } - }, - ); - } - }); + jwt.sign( + { userEmail, timestamp: Date.now() }, + process.env.JWT_RESET_TOKEN, + { + expiresIn: '7d', + }, + function (error, decoded) { + if (error) { + reject(new Error('UNABLE_TO_GENERATE_PASSWORD_RESET_TOKEN', { cause: error })); + } + resolve(decoded); + }, + ); }); }, @@ -105,30 +123,39 @@ const UserServices = { return true; }, + /** + * @description Creates a scunt token for a user + * @param {String} userId + * @returns {User} + */ async addScuntToken(userId) { const scuntToken = createScuntToken(); - return new Promise((resolve, reject) => { - UserModel.findByIdAndUpdate( - userId, - { scuntToken }, - { returnDocument: 'after' }, - (err, user) => { - if (err || !user) { - reject('UNABLE_TO_UPDATE_SCUNT_TOKEN_FOR_USER'); - } else { - resolve(user); - } - }, - ); - }); + return UserModel.findByIdAndUpdate( + userId, + { scuntToken }, + { new: true, returnDocument: 'after' }, + ).then( + (user) => { + if (!user) throw new Error('USER_NOT_FOUND'); + return user; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_SCUNT_TOKEN_FOR_USER', { cause: error }); + }, + ); }, + /** + * @description Validates a password reset token + * @param {String} token + * @returns {decodedToken} + */ async validatePasswordResetToken(token) { return new Promise((resolve, reject) => { jwt.verify(token, process.env.JWT_RESET_TOKEN, (err, decoded) => { if (err) { - reject(err); + reject(new Error('UNABLE_TO_VALIDATE_PASSWORD_RESET_TOKEN', { cause: err })); } else { resolve(decoded); } @@ -136,11 +163,16 @@ const UserServices = { }); }, + /** + * @description Validates a email confirmation token + * @param {String} token + * @returns {decodedToken} + */ async validateEmailConfirmationToken(token) { return new Promise((resolve, reject) => { - jwt.verify(token, process.env.JWT_EMAIL_CONFIRMATION_TOKEN, (err, decoded) => { - if (err) { - reject(err); + jwt.verify(token, process.env.JWT_EMAIL_CONFIRMATION_TOKEN, (error, decoded) => { + if (error) { + reject(new Error('UNABLE_TO_VALIDATE_EMAIL_CONFIRMATION_TOKEN', { cause: error })); } else { resolve(decoded); } @@ -148,195 +180,226 @@ const UserServices = { }); }, + /** + * @description Gets a user by email + * @param {String} email + * @returns {User} + */ async getUserByEmail(email) { - return new Promise((resolve, reject) => { - UserModel.findOne({ email }, (err, user) => { - if (err) { - reject(err); - } else { - resolve(user); - } - }); - }); + return UserModel.findOne({ email }).then( + (user) => { + if (!user) throw new Error('USER_NOT_FOUND'); + return user; + }, + (error) => { + throw new Error('UNABLE_TO_GET_USER', { cause: error }); + }, + ); }, + /** + * @description Gets a user by id + * @param {String} userID + * @returns {User} + */ async getUserByID(userID) { - return new Promise((resolve, reject) => { - UserModel.findOne({ _id: userID }, (err, user) => { - if (err) { - reject(err); - } else { - resolve(user); - } - }); - }); + return UserModel.findById(userID).then( + (user) => { + if (!user) throw new Error('USER_NOT_FOUND'); + return user; + }, + (error) => { + throw new Error('UNABLE_TO_GET_USER', { cause: error }); + }, + ); }, + /** + * @description Gets all users + * @returns {User[]} + */ async getAllUsers() { - return new Promise((resolve, reject) => { - UserModel.find({}, (err, users) => { - if (err) { - reject(err); - } else { - resolve(users); - } - }); - }); + return UserModel.find({}).then( + (users) => { + if (!users.length) throw new Error('USERS_NOT_FOUND'); + return users; + }, + (error) => { + throw new Error('UNABLE_TO_GET_USERS', { cause: error }); + }, + ); }, + /** + * @description Updates a user's password + * @param {String} email + * @param {String} password + * @returns {User} + */ async updatePassword(email, password) { const passwordValidator = /(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[~`_=^:();<>+-.@$!%*#?&])[A-Za-z0-9@$_=!%:*#?&.]{8,}/; - if (!passwordValidator.test(password)) { - throw new Error('INVALID_PASSWORD'); - } - return new Promise((resolve, reject) => { - bcrypt.hash(password, 10).then((hashedPassword) => { - UserModel.findOneAndUpdate( - { email }, - { hashedPassword }, - { returnDocument: 'after' }, - (err, updatedUser) => { - if (err) { - reject(err); - } else if (!updatedUser) { - reject('INVALID_EMAIL'); - } else { - resolve(updatedUser); - } - }, - ); - }); - }); + if (!passwordValidator.test(password)) throw new Error('INVALID_PASSWORD'); + + const hashedPassword = await bcrypt.hash(password, 10); + + return UserModel.findOneAndUpdate( + { email }, + { hashedPassword }, + { returnDocument: 'after' }, + ).then( + (user) => { + if (!user) throw new Error('USER_NOT_FOUND'); + return user; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_PASSWORD_FOR_USER', { cause: error }); + }, + ); }, - async requestAuthScopes(user, scopes) { - return new Promise((resolve, reject) => { - UserModel.findByIdAndUpdate( - user.id, - { 'authScopes.requested': scopes }, - { returnDocument: 'after' }, - (err, updatedUser) => { - if (err) { - reject(err); - } else if (!updatedUser) { - reject('INVALID_USER'); - } else { - resolve(updatedUser); - } - }, - ); - }); + /** + * @description Updates a user's Auth Scopes + * @param {String} userID + * @param {String[]} scopes + * @returns {User} + */ + async requestAuthScopes(userID, scopes) { + return UserModel.findByIdAndUpdate( + userID, + { 'authScopes.requested': scopes }, + { returnDocument: 'after' }, + ).then( + (updatedUser) => { + if (!updatedUser) throw new Error('USER_NOT_FOUND'); + return updatedUser; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_AUTH_SCOPES_FOR_USER', { cause: error }); + }, + ); }, + /** + * @description Unsubscribes a user from emails + * @param {String} email + * @returns {User} + */ async unsubscribeUser(email) { - return new Promise((resolve, reject) => { - UserModel.findOneAndUpdate( - { email }, - { canEmail: false }, - { returnDocument: 'after' }, - (err, updatedUser) => { - if (err) { - reject(err); - } else if (!updatedUser) { - reject('INVALID_EMAIL'); - } else { - resolve(updatedUser); - } - }, - ); - }); + return UserModel.findOneAndUpdate( + { email }, + { canEmail: false }, + { returnDocument: 'after' }, + ).then( + (updatedUser) => { + if (!updatedUser) throw new Error('USER_NOT_FOUND'); + return updatedUser; + }, + (error) => { + throw new Error('UNABLE_TO_UNSUBSCRIBE_USER', { cause: error }); + }, + ); }, + /** + * @description Resubscribes a user from emails + * @param {String} email + * @returns {User} + */ async resubscribeUser(email) { - return new Promise((resolve, reject) => { - UserModel.findOneAndUpdate( - { email }, - { canEmail: true }, - { returnDocument: 'after' }, - (err, updatedUser) => { - if (err) { - reject(err); - } else if (!updatedUser) { - reject('INVALID_EMAIL'); - } else { - resolve(updatedUser); - } - }, - ); - }); + return UserModel.findOneAndUpdate( + { email }, + { canEmail: true }, + { returnDocument: 'after' }, + ).then( + (updatedUser) => { + if (!updatedUser) throw new Error('USER_NOT_FOUND'); + return updatedUser; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_AUTH_SCOPES_FOR_USER', { cause: error }); + }, + ); }, + /** + * @description Gets all users who have not been approved + * @returns {User[]} + */ async getUnapprovedUsers() { - return new Promise((resolve, reject) => { - UserModel.find( - { approved: { $exists: true, $eq: false } }, - {}, - { strictQuery: false }, - (err, users) => { - if (err) { - reject(err); - } else if (!users) { - reject('INTERNAL_ERROR'); - } else { - resolve(users); - } - }, - ); - }); + return UserModel.find( + { approved: { $exists: true, $eq: false } }, + {}, + { strictQuery: false }, + ).then( + (users) => { + if (!users.length) throw new Error('USERS_NOT_FOUND'); + return users; + }, + (error) => { + throw new Error('UNABLE_TO_FIND_USERS', { cause: error }); + }, + ); }, + /** + * @description Get a users auth scopes + * @returns {String[]} + */ async getUsersAuthScopes() { - return new Promise((resolve, reject) => { - UserModel.find( - { - $or: [ - { 'authScopes.requested': { $exists: true, $ne: [] } }, - { 'froshDataFields.requested': { $exists: true, $ne: [] } }, - { 'authScopes.approved': { $exists: true, $ne: [] } }, - { 'froshDataFields.approved': { $exists: true, $ne: [] } }, - ], - }, - {}, - { strictQuery: false }, - (err, users) => { - if (err) { - reject(err); - } else if (!users) { - reject('INTERNAL_ERROR'); - } else { - resolve(users); - } - }, - ); - }); + return UserModel.find( + { + $or: [ + { 'authScopes.requested': { $exists: true, $ne: [] } }, + { 'froshDataFields.requested': { $exists: true, $ne: [] } }, + { 'authScopes.approved': { $exists: true, $ne: [] } }, + { 'froshDataFields.approved': { $exists: true, $ne: [] } }, + ], + }, + {}, + { strictQuery: false }, + ).then( + (users) => { + if (!users.length) throw new Error('USERS_NOT_FOUND'); + return users; + }, + (error) => { + throw new Error('UNABLE_TO_FIND_USERS', { cause: error }); + }, + ); }, + /** + * @description approve users by ids + * @param {String[]} accountIds + * @returns {User[]} + */ async approveAccountsByIds(accountIds) { - console.log('accountIds', accountIds); - return new Promise((resolve, reject) => { - UserModel.collection.updateMany( - { _id: { $in: accountIds.map((id) => mongoose.Types.ObjectId(id)) } }, + return UserModel.collection + .updateMany( + { _id: { $in: accountIds.map((id) => new mongoose.Types.ObjectId(id)) } }, { $set: { approved: true } }, { strictQuery: false }, - (err, result) => { - if (err) { - console.log(err); - reject(err); - } else if (!result) { - reject('INTERNAL_ERROR'); - } else { - console.log('result', result); - resolve(result); - } + ) + .then( + (results) => { + if (results.matchedCount !== accountIds.length) throw new Error('USERS_NOT_FOUND'); + return results; + }, + (error) => { + throw new Error('UNABLE_TO_APPROVE_USERS', { cause: error }); }, ); - }); }, + /** + * @description update users auth scopes + * @param {String[]} userAuthScopes + * @returns {String[]} + */ async updateAuthScopes(userAuthScopes) { - return new Promise((resolve, reject) => { - UserModel.collection.bulkWrite( + return UserModel.collection + .bulkWrite( userAuthScopes.map((user) => { const { authScopesApproved, @@ -369,7 +432,7 @@ const UserServices = { ); return { updateOne: { - filter: { _id: { $eq: mongoose.Types.ObjectId(user.id) } }, + filter: { _id: { $eq: new mongoose.Types.ObjectId(user.id) } }, update: { $set: { 'authScopes.approved': [...new Set(authScopesApproved)], @@ -381,79 +444,80 @@ const UserServices = { }, }; }), - (err, result) => { - if (err) { - console.log(err); - reject(err); - } else { - console.log(result); - resolve(result); - } + ) + .then( + (results) => { + if (results.modifiedCount !== userAuthScopes.length) throw new Error('USERS_NOT_FOUND'); + return results; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_USERS', { cause: error }); }, ); - }); }, + /** + * @description Get all scunt judges + * @returns {User[]} + */ async getScuntJudgeUsers() { - return new Promise((resolve, reject) => { - UserModel.find( - { - $or: [ - { 'authScopes.approved': 'scunt:judge bribe points' }, - { 'authScopes.approved': 'scunt:judge missions' }, - // { 'authScopes.approved': 'scunt:bribe points' }, // this was the wrong scope name i think.... - // { 'authScopes.approved': 'scunt:judge missions' }, - ], - }, - {}, - { strictQuery: false }, - (err, users) => { - if (err) { - reject(err); - } else if (!users) { - reject('INTERNAL_ERROR'); - } else { - resolve(users); - } - }, - ); - }); + return UserModel.find( + { + $or: [ + { 'authScopes.approved': 'scunt:judge bribe points' }, + { 'authScopes.approved': 'scunt:judge missions' }, + // { 'authScopes.approved': 'scunt:bribe points' }, // this was the wrong scope name i think.... + // { 'authScopes.approved': 'scunt:judge missions' }, + ], + }, + {}, + { strictQuery: false }, + ).then( + (users) => { + if (!users.length) throw new Error('USERS_NOT_FOUND'); + return users; + }, + (error) => { + throw new Error('UNABLE_TO_FIND_USERS', { cause: error }); + }, + ); }, + /** + * @description Updates a user's info + * @param {String} userId + * @param {Object} updateInfo + * @returns {User} + */ async updateUserInfo(userId, updateInfo) { - return new Promise((resolve, reject) => { - UserModel.findOneAndUpdate( - { _id: userId }, - updateInfo, - { returnDocument: 'after' }, - (err, User) => { - if (err || !User) { - reject('UNABLE_TO_UPDATE_USER'); - } else { - console.log(User); - resolve(User); - } - }, - ); - }); + return UserModel.findByIdAndUpdate(userId, updateInfo, { + returnDocument: 'after', + }).then( + (user) => { + if (!user) throw new Error('USER_NOT_FOUND'); + return user; + }, + (error) => { + throw new Error('UNABLE_TO_UPDATE_USER', { cause: error }); + }, + ); }, /** - * Hard deletes a user by id. + * @description Hard deletes a user by id. * @param {ObjectId} id - id of the user to be deleted - * @async - * @return {Promise} - the user which was deleted + * @return {User} - the user which was deleted */ async deleteUser(id) { - return new Promise((resolve, reject) => { - UserModel.findOneAndDelete({ _id: id }, (err, deletedUser) => { - if (err || !deletedUser) { - reject('UNABLE_TO_DELETE_USER'); - } else { - resolve(deletedUser); - } - }); - }); + return UserModel.findByIdAndDelete(id).then( + (deletedUser) => { + if (!deletedUser) throw new Error('USER_NOT_FOUND'); + return deletedUser; + }, + (error) => { + throw new Error('UNABLE_TO_DELETE_USER', { cause: error }); + }, + ); }, }; diff --git a/server/src/services/passport.js b/server/src/services/passport.js index 0f8a509c..4093996c 100644 --- a/server/src/services/passport.js +++ b/server/src/services/passport.js @@ -8,9 +8,12 @@ passport.serializeUser((user, done) => { }); passport.deserializeUser((id, done) => { - User.findById(id, (err, user) => { - done(err, user); - }); + User.findById(id).then( + (user) => { + done(null, user); + }, + (error) => done(new Error('UNABLE_TO_DESERIALIZE_USER', { cause: error }), null), + ); }); passport.use( @@ -18,11 +21,11 @@ passport.use( User.findOne({ email: email.toLowerCase() }) .then((user) => { if (!user) { - return done(null, false, { message: 'NO_USER' }); + return done(new Error('USER_NOT_FOUND')); } - bcrypt.compare(password, user.hashedPassword, (err, isMatch) => { - if (err) { - throw err; + bcrypt.compare(password, user.hashedPassword, (error, isMatch) => { + if (error) { + throw done(new Error('UNABLE_TO_VERIFY_PASSWORD', { cause: error })); } if (isMatch) { return done(null, user); @@ -31,9 +34,7 @@ passport.use( } }); }) - .catch((err) => { - return done(null, false, { message: err }); - }); + .catch((error) => done(new Error('UNABLE_TO_FIND_USER', { cause: error }))); }), ); diff --git a/server/src/subscribers/announcementSubscription.js b/server/src/subscribers/announcementSubscription.js index 6895e20f..4c1f68a1 100644 --- a/server/src/subscribers/announcementSubscription.js +++ b/server/src/subscribers/announcementSubscription.js @@ -55,8 +55,7 @@ announcementSubscription.process((job, done) => { ); result.then((response) => { - console.log('response:'); - console.log(response); + console.log('email API response:', response); done(); }); }); diff --git a/server/src/subscribers/emailConfirmationSubscription.js b/server/src/subscribers/emailConfirmationSubscription.js index 32d48895..73fab192 100644 --- a/server/src/subscribers/emailConfirmationSubscription.js +++ b/server/src/subscribers/emailConfirmationSubscription.js @@ -1,6 +1,5 @@ const Queue = require('bull'); const EmailServices = require('../services/EmailServices'); -const jwt = require('jsonwebtoken'); const emailConfirmationSubscription = new Queue('newUser', { redis: { port: process.env.REDIS_PORT, host: 'redis', password: process.env.REDIS_PASSWORD }, @@ -9,21 +8,20 @@ const emailConfirmationSubscription = new Queue('newUser', { emailConfirmationSubscription.process((job, done) => { try { // sending user email verification link - const emailToken = jwt.sign( - job.data.email, - process.env.JWT_EMAIL_CONFIRMATION_TOKEN, - ); - + const emailToken = job.data.token; + const url = process.env.CLIENT_BASE_URL + '/verify-user-email/' + job.data.email + '/' + emailToken; - + EmailServices.sendSimpleEmail( [job.data.email], '', 'Please use this URL to confirm your email: ' + url, 'F!rosh Email Confirmation', 'tech@orientation.skule.ca', - ); + ).then((response) => { + console.log('Email API response', response); + }); done(); } catch (error) { done(error); diff --git a/server/src/subscribers/newUserSubscription.js b/server/src/subscribers/newUserSubscription.js index ca8e3f77..14a36348 100644 --- a/server/src/subscribers/newUserSubscription.js +++ b/server/src/subscribers/newUserSubscription.js @@ -8,13 +8,12 @@ const newUserSubscription = new Queue('existingUser', { newUserSubscription.process((job, done) => { try { // sending successful user creation email - const result = EmailServices.sendTemplateEmail( + EmailServices.sendTemplateEmail( {}, 'signup_confirmation', [job.data.email], 'tech@orientation.skule.ca', - ); - result.then((response) => { + ).then((response) => { console.log('Email API response', response); }); done(); diff --git a/server/src/tests/db.js b/server/src/tests/db.js deleted file mode 100644 index 9dcaa257..00000000 --- a/server/src/tests/db.js +++ /dev/null @@ -1,26 +0,0 @@ -const mongoose = require('mongoose'); -const { MongoMemoryServer } = require('mongodb-memory-server'); -const newUserSubscription = require('../subscribers/newUserSubscription'); - -let mongod; - -module.exports.connect = async () => { - mongod = await MongoMemoryServer.create(); - const uri = mongod.getUri(); - await mongoose.connect(uri); -}; - -module.exports.closeDatabase = async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await newUserSubscription.close(); - await mongod.stop(); -}; - -module.exports.clearDatabase = async () => { - const collections = mongoose.connection.collections; - for (const key in collections) { - const collection = collections[key]; - await collection.deleteMany(); - } -}; diff --git a/server/src/tests/frosh.test.js b/server/src/tests/frosh.test.js deleted file mode 100644 index 4a7f1c6d..00000000 --- a/server/src/tests/frosh.test.js +++ /dev/null @@ -1,30 +0,0 @@ -const request = require('supertest'); -const app = require('../app'); -const db = require('./db'); - -describe('Test the root path', () => { - test('It should respond to the GET method', () => { - return request(app) - .get('/') - .then((response) => { - expect(response.statusCode).toBe(200); - }); - }); -}); - -describe('frosh routes', () => { - beforeAll(async () => { - await db.connect(); - }); - afterAll(async () => { - await db.closeDatabase(); - }); - afterEach(async () => { - await db.clearDatabase(); - }); - // Placeholder test so that the tests run - test('Placeholder test', () => { - const result = 1 + 1; - expect(result).toBe(2); - }); -}); diff --git a/server/src/websockets/ScuntLeaderboardSocketManager.js b/server/src/websockets/ScuntLeaderboardSocketManager.js index aaf2e124..05cbf448 100644 --- a/server/src/websockets/ScuntLeaderboardSocketManager.js +++ b/server/src/websockets/ScuntLeaderboardSocketManager.js @@ -16,7 +16,7 @@ class ScuntLeaderboardSocketManager { async initSettings() { const currentSettings = await ScuntGameSettingServices.getGameSettings(); - this.settings = currentSettings[0]; + this.settings = currentSettings; } addSocket(socket) { @@ -33,10 +33,14 @@ class ScuntLeaderboardSocketManager { async getScores(socket) { console.log('Getting scores!'); - console.log(this.settings.revealLeaderboard); - if (this.settings.revealLeaderboard) { - const scores = await ScuntTeamServices.getTeamPoints(); - socket.emit('scores', scores); + console.log(this.settings?.revealLeaderboard); + if (this.settings?.revealLeaderboard) { + try { + const scores = await ScuntTeamServices.getTeamPoints(); + socket.emit('scores', scores); + } catch (e) { + console.log(e); + } } } @@ -47,7 +51,7 @@ class ScuntLeaderboardSocketManager { data: { team, score }, } = job; const lastUpdated = this.teamUpdateTimes.get(team) ?? 0; - if (timestamp >= lastUpdated && this.settings.revealLeaderboard) { + if (timestamp >= lastUpdated && this.settings?.revealLeaderboard) { this.sendUpdate(team, score); this.teamUpdateTimes.set(team, timestamp); } @@ -63,15 +67,20 @@ class ScuntLeaderboardSocketManager { const newSettings = job.data; if (!newSettings) { return done(); - } else if (newSettings.revealLeaderboard) { + } else if (newSettings?.revealLeaderboard) { console.log('Revealing leaderboard!'); - ScuntTeamServices.getTeamPoints().then((scores) => { - console.log('team scores'); - console.log(scores); - this.io.to('leaderboard').emit('scores', scores); - this.settings = newSettings ?? this.settings; - return done(); - }); + ScuntTeamServices.getTeamPoints().then( + (scores) => { + console.log('team scores'); + console.log(scores); + this.io.to('leaderboard').emit('scores', scores); + this.settings = newSettings ?? this.settings; + return done(); + }, + (error) => { + done(error); + }, + ); } else { this.settings = newSettings ?? this.settings; console.log(this.settings); diff --git a/server/test/dbconfig.test.js b/server/test/dbconfig.test.js new file mode 100644 index 00000000..2789768e --- /dev/null +++ b/server/test/dbconfig.test.js @@ -0,0 +1,26 @@ +/* eslint-disable no-undef */ +const mongoose = require('mongoose'); +const mongoURI = `mongodb://admin:root@127.0.0.1:27017/testingDatabase?authSource=admin`; + +mongoose.connect(mongoURI); + +mongoose.connection + .once('open', () => + mongoose.connection.dropDatabase().then(() => { + done(); + }), + ) + .on('error', (error) => { + console.warn('Error : ', error); + }); + +// Drop the database before each test +beforeEach((done) => { + if (mongoose.connection.readyState === 0) { + mongoose.connect(mongoURI, (err) => { + if (err) throw err; + return done(); + }); + } + done(); +}); diff --git a/server/test/routers/announcementRoutes.test.js b/server/test/routers/announcementRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/faqRoutes.test.js b/server/test/routers/faqRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/froshRoutes.test.js b/server/test/routers/froshRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/paymentRoutes.test.js b/server/test/routers/paymentRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/qrRoutes.test.js b/server/test/routers/qrRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/scuntGameSettingsRoutes.test.js b/server/test/routers/scuntGameSettingsRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/scuntMissionRoutes.test.js b/server/test/routers/scuntMissionRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/scuntRoutes.test.js b/server/test/routers/scuntRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/scuntTeamRoutes.test.js b/server/test/routers/scuntTeamRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/timelineRoutes.test.js b/server/test/routers/timelineRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/routers/userRoutes.test.js b/server/test/routers/userRoutes.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/services/AnnouncementServices.test.js b/server/test/services/AnnouncementServices.test.js new file mode 100644 index 00000000..b22e34b9 --- /dev/null +++ b/server/test/services/AnnouncementServices.test.js @@ -0,0 +1,216 @@ +/* eslint-disable no-undef */ +const AnnouncementServices = require('../../src/services/AnnouncementServices'); +const UserModel = require('../../src/models/UserModel'); +const assert = require('assert'); + +describe('AnnouncementsServices', () => { + let createdAnnouncement; + + it('.create()\t\t\t|\tCreate an announcement', async () => { + const announcement = { + name: 'Test Announcement', + description: 'This is a test announcement', + sendAsEmail: true, + }; + createdAnnouncement = await AnnouncementServices.create(announcement); + assert(createdAnnouncement.name === 'Test Announcement'); + assert(createdAnnouncement.description === 'This is a test announcement'); + }); + + it('.create()\t\t\t|\tCreate multiple announcements', async () => { + const announcement = { + name: 'Test Announcement', + description: 'This is a test announcement', + sendAsEmail: false, + }; + await AnnouncementServices.create(announcement); + await AnnouncementServices.create(announcement); + await AnnouncementServices.create(announcement); + await AnnouncementServices.create(announcement); + await AnnouncementServices.create(announcement); + }); + + it('.create()\t\t\t|\tCreate an announcement (INVALID ANNOUNCEMENT)', async () => { + const announcement = { + description: 'This is a test announcement', + sendAsEmail: false, + }; + await assert.rejects(AnnouncementServices.create(announcement), { + name: 'Error', + message: 'UNABLE_TO_CREATE_ANNOUNCEMENT', + }); + }); + + it('.getAll()\t\t\t|\tShould return an array of announcements', async () => { + const announcements = await AnnouncementServices.getAll(); + assert.notEqual(announcements.length, 0); + assert.equal(announcements.length, 6); + assert( + announcements.every( + (announcement) => + announcement.name === 'Test Announcement' && + announcement.description === 'This is a test announcement', + ), + ); + }); + + it(".update()\t\t\t|\tShould update an announcement's name", async () => { + const updatedAnnouncement = await AnnouncementServices.update(createdAnnouncement.id, { + name: 'Updated Announcement', + }); + assert.equal(updatedAnnouncement.name, 'Updated Announcement'); + assert.equal(updatedAnnouncement.id, createdAnnouncement.id); + }); + + it(".update()\t\t\t|\tShould update an announcement's description", async () => { + const updatedAnnouncement = await AnnouncementServices.update(createdAnnouncement.id, { + description: 'Updated Announcement Description', + }); + assert.equal(updatedAnnouncement.description, 'Updated Announcement Description'); + assert.equal(updatedAnnouncement.id, createdAnnouncement.id); + }); + + it('.update()\t\t\t|\tShould update an announcement (INVALID ID)', async () => { + await assert.rejects( + AnnouncementServices.update('createdAnnouncement.id', { + description: 'Updated Announcement Description', + }), + { name: 'Error', message: 'UNABLE_TO_UPDATE_ANNOUNCEMENT' }, + ); + }); + + it('.delete()\t\t\t|\tShould delete an announcement', async () => { + const deletedAnnouncement = await AnnouncementServices.delete(createdAnnouncement.id); + assert.equal(deletedAnnouncement.id, createdAnnouncement.id); + }); + + it('.delete()\t\t\t|\tCheck deleted announcement (DELETED ID)', async () => { + await assert.rejects(AnnouncementServices.delete(createdAnnouncement.id), { + name: 'Error', + message: 'ANNOUNCEMENT_NOT_FOUND', + }); + }); + + it('.delete()\t\t\t|\tCheck deleted announcement (INVALID ID)', async () => { + await assert.rejects(AnnouncementServices.delete(''), { + name: 'Error', + message: 'UNABLE_TO_DELETE_ANNOUNCEMENT', + }); + }); + + it('.update()\t\t\t|\tShould update an announcement (DELETED ID)', async () => { + await assert.rejects( + AnnouncementServices.update(createdAnnouncement.id, { + description: 'Updated Announcement Description', + }), + { name: 'Error', message: 'ANNOUNCEMENT_NOT_FOUND' }, + ); + }); + + let testUser; + let toComplete; + it('.complete(id, userID)\t|\tMark an announcement as complete for a user', async () => { + testUser = await UserModel.create({ + firstName: 'Test', + lastName: 'User', + email: 'test@test1.com', + hashedPassword: 'test', + }); + const announcement = { + name: 'Test Announcement', + description: 'This is a test announcement', + sendAsEmail: false, + }; + toComplete = await AnnouncementServices.create(announcement); + const completedAnnouncements = await AnnouncementServices.complete(toComplete.id, testUser.id); + assert.equal(completedAnnouncements.length, 1); + assert.equal(completedAnnouncements[0].announcementID, toComplete.id); + assert.equal(completedAnnouncements[0].announcementName, toComplete.name); + }); + + it('.getCompleted(id)\t\t|\tShould return an array of completed announcements', async () => { + const completedAnnouncements = await AnnouncementServices.getCompleted(testUser); + assert.equal(completedAnnouncements.length, 1); + assert.equal(completedAnnouncements[0].id, toComplete.id); + assert.equal(completedAnnouncements[0].name, toComplete.name); + }); + + it('.getCompleted(id)\t\t|\tShould return an array of completed announcements (INVALID ANNOUNCEMENT ID)', async () => { + const user = await UserModel.create({ + firstName: 'Test', + lastName: 'User', + email: 'test1@test.com', + hashedPassword: 'test', + completedAnnouncements: [ + { + announcementID: '', + }, + ], + }); + await assert.rejects(AnnouncementServices.getCompleted(user.id), { + name: 'Error', + message: 'UNABLE_TO_GET_COMPLETED_ANNOUNCEMENTS', + }); + }); + + it('.getCompleted(id)\t\t|\tShould return an array of completed announcements (INVALID USER ID)', async () => { + await assert.rejects(AnnouncementServices.getCompleted(''), { + name: 'Error', + message: 'UNABLE_TO_GET_USER', + }); + }); + + it('.complete(id, userID)\t|\tMark an announcement as incomplete for a user', async () => { + const completedAnnouncements = await AnnouncementServices.complete(toComplete.id, testUser.id); + assert.equal(completedAnnouncements.length, 0); + }); + + it('.complete(id, userID)\t|\tMark an announcement as complete for a user (DUPLICATE)', async () => { + const announcement = { + name: 'Test Announcement', + description: 'This is a test announcement', + sendAsEmail: false, + }; + toComplete = await AnnouncementServices.create(announcement); + const completedAnnouncements = await AnnouncementServices.complete(toComplete.id, testUser.id); + assert.equal(completedAnnouncements.length, 1); + assert.equal(completedAnnouncements[0].announcementID, toComplete.id); + assert.equal(completedAnnouncements[0].announcementName, toComplete.name); + }); + + it('.complete(id, userID)\t|\tMark an announcement as complete (INVALID ANNOUNCEMENT ID)', async () => { + await assert.rejects(AnnouncementServices.complete('', testUser), { + name: 'Error', + message: 'UNABLE_TO_GET_ANNOUNCEMENT', + }); + }); + + it('.complete(id, userID)\t|\tMark an announcement as complete (DELETED ANNOUNCEMENT ID)', async () => { + await assert.rejects(AnnouncementServices.complete(createdAnnouncement.id, testUser), { + name: 'Error', + message: 'ANNOUNCEMENT_NOT_FOUND', + }); + }); + + it('.complete(id, userID)\t|\tMark an announcement as complete (INVALID USER)', async () => { + await assert.rejects(AnnouncementServices.complete(toComplete.id, ''), { + name: 'Error', + message: 'UNABLE_TO_GET_USER', + }); + }); + + it('.complete(id, userID)\t|\tMark an announcement as complete (DELETED USER)', async () => { + await UserModel.deleteOne({ _id: testUser.id }); + await assert.rejects(AnnouncementServices.complete(toComplete.id, testUser.id), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.getCompleted(id)\t\t|\tShould return an array of completed announcements (DELETED USER ID)', async () => { + await assert.rejects(AnnouncementServices.getCompleted(testUser.id), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); +}); diff --git a/server/test/services/EmailServices.test.js b/server/test/services/EmailServices.test.js new file mode 100644 index 00000000..e69de29b diff --git a/server/test/services/FaqServices.test.js b/server/test/services/FaqServices.test.js new file mode 100644 index 00000000..779abc35 --- /dev/null +++ b/server/test/services/FaqServices.test.js @@ -0,0 +1,138 @@ +/* eslint-disable no-undef */ +const FaqServices = require('../../src/services/FaqServices'); +const assert = require('assert'); + +describe('FaqServices', () => { + let createdFaq; + it('.getAll()', async () => { + await assert.rejects(FaqServices.getAll(), { + name: 'Error', + message: 'FAQS_NOT_FOUND', + }); + }); + + it('.getAnswered()', async () => { + await assert.rejects(FaqServices.getAnswered(), { + name: 'Error', + message: 'FAQS_NOT_FOUND', + }); + }); + + it('.getUnanswered()', async () => { + await assert.rejects(FaqServices.getUnanswered(), { + name: 'Error', + message: 'FAQS_NOT_FOUND', + }); + }); + + it('.create()', async () => { + createdFaq = await FaqServices.create( + 'test@test.com', + 'Test Question', + 'Test Answer', + 'Test Category', + ); + assert.equal(createdFaq.email, 'test@test.com'); + assert.equal(createdFaq.question, 'Test Question'); + assert.equal(createdFaq.answer, 'Test Answer'); + assert.equal(createdFaq.isAnswered, true); + assert.equal(createdFaq.category, 'Test Category'); + }); + + it('.create() no answer', async () => { + const faq = await FaqServices.create('test@test.com', 'Test Question', '', 'Test Category'); + assert.equal(faq.email, 'test@test.com'); + assert.equal(faq.question, 'Test Question'); + assert.equal(faq.answer, ''); + assert.equal(faq.isAnswered, false); + assert.equal(faq.category, 'Test Category'); + }); + + it('.create() no category', async () => { + const faq = await FaqServices.create('test@test.com', 'Test Question', 'Test Answer', ''); + assert.equal(faq.email, 'test@test.com'); + assert.equal(faq.question, 'Test Question'); + assert.equal(faq.answer, 'Test Answer'); + assert.equal(faq.isAnswered, true); + assert.equal(faq.category, 'General'); + }); + + it('.create() no category no answer', async () => { + const faq = await FaqServices.create('test@test.com', 'Test Question', '', ''); + assert.equal(faq.email, 'test@test.com'); + assert.equal(faq.question, 'Test Question'); + assert.equal(faq.answer, ''); + assert.equal(faq.isAnswered, false); + assert.equal(faq.category, 'General'); + }); + + it('.getAll()', async () => { + const faqs = await FaqServices.getAll(); + assert.equal(faqs.length, 4); + }); + + it('.getAnswered()', async () => { + const faqs = await FaqServices.getAnswered(); + assert.equal(faqs.length, 2); + }); + + it('.getUnanswered()', async () => { + const faqs = await FaqServices.getUnanswered(); + assert.equal(faqs.length, 2); + }); + + it('.delete(faqId)', async () => { + const faq = await FaqServices.delete(createdFaq._id); + assert.equal(faq.id, createdFaq.id); + }); + + it('.delete(faqId) invalid id', async () => { + await assert.rejects(FaqServices.delete('createdFaq._id'), { + name: 'Error', + message: 'UNABLE_TO_DELETE_FAQ', + }); + }); + + it('.delete(faqId) no faq', async () => { + await assert.rejects(FaqServices.delete('2b34b2b34b24'), { + name: 'Error', + message: 'FAQ_NOT_FOUND', + }); + }); + + it('.update(faqId, update)', async () => { + const faq = await FaqServices.update(createdFaq._id, { + question: 'Updated Question', + answer: 'Updated Answer', + }); + assert.equal(faq.id, createdFaq.id); + assert.equal(faq.question, 'Updated Question'); + assert.equal(faq.answer, 'Updated Answer'); + }); + + it('.update(faqId, update) invalid id', async () => { + await assert.rejects( + FaqServices.update('createdFaq._id', { + question: 'Updated Question', + answer: 'Updated Answer', + }), + { + name: 'Error', + message: 'UNABLE_TO_UPDATE_FAQ', + }, + ); + }); + + it('.update(faqId, update) no faq', async () => { + await assert.rejects( + FaqServices.update('2b34b2b34b24', { + question: 'Updated Question', + answer: 'Updated Answer', + }), + { + name: 'Error', + message: 'FAQ_NOT_FOUND', + }, + ); + }); +}); diff --git a/server/test/services/FroshServices.test.js b/server/test/services/FroshServices.test.js new file mode 100644 index 00000000..cca52108 --- /dev/null +++ b/server/test/services/FroshServices.test.js @@ -0,0 +1,178 @@ +/* eslint-disable no-undef */ +const FroshServices = require('../../src/services/FroshServices'); +const UserModel = require('../../src/models/UserModel'); +const FroshGroupModel = require('../../src/models/FroshGroupModel'); +const assert = require('assert'); + +describe('FroshServices', () => { + it('.getNewFroshGroup(discipline, pronouns, froshGroupList)\t|\tGetting a new Frosh Group (PREMADE LIST)', async () => { + const discipline = 'Electrical & Computer'; + const pronouns = 'she/her'; + const alphaGroup = await FroshGroupModel.create({ name: 'alpha', icon: 'α' }); + const betaGroup = await FroshGroupModel.create({ name: 'beta', icon: 'β' }); + const froshGroupList = [alphaGroup, betaGroup]; + const { froshGroup, froshGroupIcon } = await FroshServices.getNewFroshGroup( + discipline, + pronouns, + froshGroupList, + ); + assert(froshGroup === 'alpha' && froshGroupIcon === 'α'); + }); + + it('.getNewFroshGroup(discipline, pronouns, froshGroupList)\t|\tGetting a new Frosh Group (PREMADE LIST)', async () => { + const discipline = 'Electrical & Computer'; + const pronouns = 'she/her'; + const [group1] = await FroshGroupModel.find({}); + + group1['Electrical & Computer'] = 100; + await group1.save(); + await FroshServices.getNewFroshGroup(discipline, pronouns); + + group1['Electrical & Computer'] = 0; + await group1.save(); + }); + + it('.getNewFroshGroup(discipline, pronouns, froshGroupList)\t|\tGetting a new Frosh Group (Using .find() FroshGroupModel)', async () => { + const discipline = 'Electrical & Computer'; + const pronouns = 'she/her'; + const { froshGroup, froshGroupIcon } = await FroshServices.getNewFroshGroup( + discipline, + pronouns, + ); + assert(froshGroup === 'alpha' && froshGroupIcon === 'α'); + }); + + it('.initFroshGroups(groups)\t\t\t\t\t|\tInitializing Frosh Groups', async () => { + const groups = [ + { + name: 'alpha', + icon: 'α', + }, + { + name: 'beta', + icon: 'α', + }, + { + name: 'gamma', + icon: 'γ', + }, + { + name: 'delta', + icon: 'δ', + }, + { + name: 'epsilon', + icon: 'ε', + }, + ]; + const froshGroupList = await FroshServices.initFroshGroups(groups); + assert(froshGroupList[1].name === 'beta'); + }); + + let frosh; + let paymentIntent; + it('.upgradeToFrosh(user, newInfo, paymentIntent)\t\t|\tUpgrading User to Frosh', async () => { + paymentIntent = 'succeeded'; + const user = await UserModel.create({ + firstName: 'Test', + lastName: 'User', + email: 'froshtest@test.com', + hashedPassword: 'test', + }); + const user2 = await UserModel.create({ + firstName: 'Test2', + lastName: 'User2', + email: 'froshtest2@test.com', + hashedPassword: 'test2', + }); + await UserModel.create({ + firstName: 'Test3', + lastName: 'User3', + email: 'froshtest3@test.com', + hashedPassword: 'test3', + }); + const newInfo = { + legalName: 'test', + pronouns: 'she/her', + birthDate: '01-01-1900', + utorid: 'test', + discipline: 'Electrical & Computer', + shirtSize: 'M', + phoneNumber: '000-000-0000', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: '000-000-0000', + attendingScunt: true, + summerLocationCity: 'Toronto', + summerLocationCountry: 'Canada', + photograph: true, + froshGroup: 'alpha', + froshGroupIcon: 'α', + }; + frosh = await FroshServices.upgradeToFrosh(user, newInfo, paymentIntent); + await FroshServices.upgradeToFrosh(user2, newInfo, paymentIntent); + assert(frosh.froshGroup === 'alpha'); + }); + + it('.addRetreatPayment(user, paymentIntent)\t\t\t|\tAdding Retreat Payment to Frosh (INVALID USER)', async () => { + const fakeUser = { id: '999999' }; + await assert.rejects(FroshServices.addRetreatPayment(fakeUser, paymentIntent), { + name: 'Error', + message: 'UNABLE_TO_ADD_PAYMENT', + }); + }); + + it('.addRetreatPayment(user, paymentIntent)\t\t\t|\tAdding Retreat Payment to Frosh', async () => { + const returnedFrosh = await FroshServices.addRetreatPayment(frosh, paymentIntent); + assert(returnedFrosh.froshGroup === frosh.froshGroup); + }); + + it('.getFroshInfo(id)\t\t\t\t\t\t|\tGetting Frosh', async () => { + const returnedFrosh = await FroshServices.getFroshInfo(frosh.id); + assert(returnedFrosh.froshGroup === frosh.froshGroup); + }); + + it('.getFroshInfo(id)\t\t\t\t\t\t|\tGetting Frosh (INVALID USER ID)', async () => { + await assert.rejects(FroshServices.getFroshInfo('999999'), { + name: 'Error', + message: 'UNABLE_TO_GET_FROSH', + }); + }); + + let updateInfo; + it('.updateFroshInfo(userId, updateInfo)\t\t\t|\tUpdating Frosh Information', async () => { + updateInfo = { + firstName: 'TestButUpdated', + lastName: 'UserButUpdated', + phoneNumber: '999-999-9999', + isRegistered: true, + }; + frosh = await FroshServices.updateFroshInfo(frosh.id, updateInfo); + assert(frosh.firstName === 'TestButUpdated'); + }); + + it('.updateFroshInfo(userId, updateInfo)\t\t\t|\tUpdating Frosh Information (INVALID USER ID)', async () => { + await assert.rejects(FroshServices.updateFroshInfo('999999', updateInfo), { + name: 'Error', + message: 'UNABLE_TO_UPDATE_FROSH', + }); + }); + + it('.getFilteredFroshInfo(query, projection)\t\t\t|\tGetting Frosh Information', async () => { + const query = {}; + const query2 = { isRegistered: true }; + const filter = { _id: 1 }; + const filteredFrosh = await FroshServices.getFilteredFroshInfo(query, filter); + const filteredFrosh2 = await FroshServices.getFilteredFroshInfo(query2, filter); + assert(filteredFrosh.length > 0 && filteredFrosh2.length > 0); + }); + + it('.getFilteredUserInfo(query, projection)\t\t\t|\tGetting User Information', async () => { + const query = {}; + const query2 = { isRegistered: true }; + const filter = { _id: 1 }; + const filteredUsers = await FroshServices.getFilteredUserInfo(query, filter); + const filteredUsers2 = await FroshServices.getFilteredUserInfo(query2, filter); + assert(filteredUsers.length > 0 && filteredUsers2.length > 0); + }); +}); diff --git a/server/test/services/LeadurServices.test.js b/server/test/services/LeadurServices.test.js new file mode 100644 index 00000000..e3e5d577 --- /dev/null +++ b/server/test/services/LeadurServices.test.js @@ -0,0 +1,89 @@ +/* eslint-disable no-undef */ +const LeadurServices = require('../../src/services/LeadurServices'); +assert = require('assert'); + +describe('LeadurServices', () => { + let testLeadur; + it('.createLeadur(...)\t|\tCreating a new Leadur', async () => { + testLeadur = await LeadurServices.createLeadur( + 'leadur@services.com', + 'Password!2', + 'Leadur', + 'Services', + 'Leadur', + -1, + ); + }); + + it('.createLeadur(...)\t|\tCreating a new Leadur (UNABLE_TO_HASH_PASSWORD)', async () => { + await assert.rejects( + LeadurServices.createLeadur( + 'leadur@services.com', + undefined, + 'Leadur', + 'Services', + 'Leadur', + -1, + ), + { + name: 'Error', + message: 'UNABLE_TO_HASH_PASSWORD', + }, + ); + }); + + it('.createLeadur(...)\t|\tCreating a new Leadur (UNABLE_TO_CREATE_LEEDUR)', async () => { + await assert.rejects( + LeadurServices.createLeadur( + 'leadur@services.com', + 'Password!2', + 'Leadur', + 'Services', + 'Leadur', + -1, + ), + { + name: 'Error', + message: 'UNABLE_TO_CREATE_LEEDUR', + }, + ); + }); + + it('.requestScopesAndData(...)|\tUpdating leedur permissions', async () => { + const updatedLeadur = await LeadurServices.requestScopesAndData( + testLeadur._id, + ['firstName', 'lastName', 'pronouns'], + ['read:users', 'read:groups'], + ); + assert(updatedLeadur.froshDataFields.requested.length === 3); + assert(updatedLeadur.authScopes.requested.length === 2); + }); + + it('.createLeadur(...)\t|\tCreating a new Leadur (USER_NOT_FOUND)', async () => { + await assert.rejects( + LeadurServices.requestScopesAndData( + '64e6b8d0c4d8ade85b814c44', + ['firstName', 'lastName', 'pronouns'], + ['read:users', 'read:groups'], + ), + { + name: 'Error', + message: 'USER_NOT_FOUND', + }, + ); + }); + + it('.createLeadur(...)\t|\tCreating a new Leadur (UNABLE_TO_UPDATE_LEEDUR)', async () => { + await assert.rejects( + LeadurServices.requestScopesAndData( + ' ', + ['firstName', 'lastName', 'pronouns'], + ['read:users', 'read:groups'], + ), + { + name: 'Error', + message: 'UNABLE_TO_UPDATE_LEEDUR', + }, + ); + }); +}); diff --git a/server/test/services/PaymentServices.test.js b/server/test/services/PaymentServices.test.js new file mode 100644 index 00000000..2801c70b --- /dev/null +++ b/server/test/services/PaymentServices.test.js @@ -0,0 +1,312 @@ +/* eslint-disable no-undef */ +const FroshGroupModel = require('../../src/models/FroshGroupModel'); +const FroshModel = require('../../src/models/FroshModel'); +const PaymentServices = require('../../src/services/PaymentServices'); +const assert = require('assert'); + +describe('PaymentServices', () => { + process.env.STRIPE_TICKET_PRICE_ID = 123; + process.env.STRIPE_WEBHOOK_SECRET = 123; + process.env.STRIPE_RETREAT_PRICE_ID = 123; + process.env.RETREAT_MAX_TICKETS = 123; + it('.decodeWebhookEvent(...)\t|\tDecoding a webhook event (UNABLE_TO_VERIFY_STRIPE_WEBHOOK)', async () => { + await assert.rejects(PaymentServices.decodeWebhookEvent(undefined, undefined), { + name: 'Error', + message: 'UNABLE_TO_VERIFY_STRIPE_WEBHOOK', + }); + }); + + let testFrosh; + it('.updatePayment(...)\t|\tUpdating a payment', async () => { + await FroshGroupModel.create({ + name: 'test', + totalNum: 0, + icon: 'test', + }); + testFrosh = await FroshModel.create({ + scuntPreferredMembers: [1, 2, 3], + hashedPassword: 'test', + firstName: `Test`, + lastName: `Test`, + email: `frosh@payments1.com`, + legalName: `Test`, + pronouns: 'Other', + birthDate: new Date(), + utorid: 'test123', + discipline: 'Chemical', + shirtSize: 'L', + phoneNumber: '123456', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: 'test', + bursaryRequested: false, + attendingScunt: true, + summerLocationCity: 'test', + summerLocationCountry: 'test', + photograph: true, + froshGroup: 'test', + isRegistered: false, + froshGroupIcon: 'test', + scuntTeam: 0, + payments: [ + { + item: 'Orientation Ticket', + paymentIntent: '123', + amountDue: 123, + }, + ], + }); + const updatedFrosh = await PaymentServices.updatePayment('123', 123); + assert.equal(updatedFrosh.isRegistered, true); + }); + + it('.updatePayment(...)\t|\tUpdating a payment', async () => { + await FroshGroupModel.create({ + name: 'test', + totalNum: 0, + icon: 'test', + }); + testFrosh = await FroshModel.create({ + scuntPreferredMembers: [1, 2, 3], + hashedPassword: 'test', + firstName: `Test`, + lastName: `Test`, + email: `frosh@payments2.com`, + legalName: `Test`, + pronouns: 'Other', + birthDate: new Date(), + utorid: 'test123', + discipline: 'Chemical', + shirtSize: 'L', + phoneNumber: '123456', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: 'test', + bursaryRequested: false, + attendingScunt: true, + summerLocationCity: 'test', + summerLocationCountry: 'test', + photograph: true, + froshGroup: 'test', + isRegistered: true, + froshGroupIcon: 'test', + scuntTeam: 0, + payments: [ + { + item: 'Retreat Ticket', + paymentIntent: '123456', + amountDue: 123, + }, + ], + }); + const updatedFrosh = await PaymentServices.updatePayment('123456', 123); + assert.equal(updatedFrosh.isRetreat, true); + }); + + it('.updatePayment(...)\t|\tUpdating a payment (FROSH_NOT_FOUND)', async () => { + await assert.rejects(PaymentServices.updatePayment('123452131326', 123), { + name: 'Error', + message: 'FROSH_NOT_FOUND', + }); + }); + + it('.updatePayment(...)\t|\tUpdating a payment (FROSH_GROUP_NOT_FOUND)', async () => { + await FroshModel.create({ + scuntPreferredMembers: [1, 2, 3], + hashedPassword: 'test', + firstName: `Test`, + lastName: `Test`, + email: `frosh@payments3.com`, + legalName: `Test`, + pronouns: 'Other', + birthDate: new Date(), + utorid: 'test123', + discipline: 'Chemical', + shirtSize: 'L', + phoneNumber: '123456', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: 'test', + bursaryRequested: false, + attendingScunt: true, + summerLocationCity: 'test', + summerLocationCountry: 'test', + photograph: true, + froshGroup: 'none', + isRegistered: false, + froshGroupIcon: 'test', + scuntTeam: 0, + payments: [ + { + item: 'Orientation Ticket', + paymentIntent: 'test', + amountDue: 123, + }, + ], + }); + const updatedFrosh = await PaymentServices.updatePayment('test', 123); + assert.equal(updatedFrosh.isRegistered, true); + }); + + it('.updatePayment(...)\t|\tUpdating a payment (UNABLE_TO_UPDATE_FROSH)', async () => { + await FroshModel.create({ + scuntPreferredMembers: [1, 2, 3], + hashedPassword: 'test', + firstName: `Test`, + lastName: `Test`, + email: `frosh@payments4.com`, + legalName: `Test`, + pronouns: 'Other', + birthDate: new Date(), + utorid: 'test123', + discipline: 'Chemical', + shirtSize: 'L', + phoneNumber: '123456', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: 'test', + bursaryRequested: false, + attendingScunt: true, + summerLocationCity: 'test', + summerLocationCountry: 'test', + photograph: true, + froshGroup: 'none', + isRegistered: false, + froshGroupIcon: 'test', + scuntTeam: 0, + payments: [ + { + item: 'Test 1', + paymentIntent: 'test2', + amountDue: 123, + }, + ], + }); + await assert.rejects(PaymentServices.updatePayment('test2', 123), { + name: 'Error', + message: 'UNABLE_TO_UPDATE_FROSH', + }); + }); + + it('.getNonExpiredPaymentsCountForItem(...)\t|\tGetting the number of non-expired payments for a given item', async () => { + await FroshModel.collection.drop(); + await FroshModel.create({ + scuntPreferredMembers: [1, 2, 3], + hashedPassword: 'test', + firstName: `Test`, + lastName: `Test`, + email: `frosh@payments3.com`, + legalName: `Test`, + pronouns: 'Other', + birthDate: new Date(), + utorid: 'test123', + discipline: 'Chemical', + shirtSize: 'L', + phoneNumber: '123456', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: 'test', + bursaryRequested: false, + attendingScunt: true, + summerLocationCity: 'test', + summerLocationCountry: 'test', + photograph: true, + froshGroup: 'none', + isRegistered: false, + froshGroupIcon: 'test', + scuntTeam: 0, + payments: [ + { + item: 'Orientation Ticket', + paymentIntent: 'test', + amountDue: 123, + }, + ], + }); + await FroshModel.create({ + scuntPreferredMembers: [1, 2, 3], + hashedPassword: 'test', + firstName: `Test`, + lastName: `Test`, + email: `frosh@payments4.com`, + legalName: `Test`, + pronouns: 'Other', + birthDate: new Date(), + utorid: 'test123', + discipline: 'Chemical', + shirtSize: 'L', + phoneNumber: '123456', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: 'test', + bursaryRequested: false, + attendingScunt: true, + summerLocationCity: 'test', + summerLocationCountry: 'test', + photograph: true, + froshGroup: 'none', + isRegistered: false, + froshGroupIcon: 'test', + scuntTeam: 0, + payments: [ + { + item: 'Orientation Ticket', + paymentIntent: 'test2', + amountDue: 123, + }, + ], + }); + const count = await PaymentServices.getNonExpiredPaymentsCountForItem('Orientation Ticket'); + assert.equal(count, 2); + }); + + it('.expirePayment(...)\t|\tExpiring a payment', async () => { + await FroshModel.create({ + scuntPreferredMembers: [1, 2, 3], + hashedPassword: 'test', + firstName: `Test`, + lastName: `Test`, + email: `frosh@payments5.com`, + legalName: `Test`, + pronouns: 'Other', + birthDate: new Date(), + utorid: 'test123', + discipline: 'Chemical', + shirtSize: 'L', + phoneNumber: '123456', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: 'test', + bursaryRequested: false, + attendingScunt: true, + summerLocationCity: 'test', + summerLocationCountry: 'test', + photograph: true, + froshGroup: 'none', + isRegistered: false, + froshGroupIcon: 'test', + scuntTeam: 0, + payments: [ + { + item: 'Test 1', + paymentIntent: 'test123', + amountDue: 123, + }, + { + item: 'Test 1', + paymentIntent: 'test123456', + amountDue: 123, + }, + ], + }); + const updatedFrosh = await PaymentServices.expirePayment('test123'); + assert.equal(updatedFrosh.payments[0].expired, true); + }); + + it('.expirePayment(...)\t|\tExpiring a payment (FROSH_NOT_FOUND)', async () => { + await assert.rejects(PaymentServices.expirePayment('none existent'), { + name: 'Error', + message: 'FROSH_NOT_FOUND', + }); + }); +}); diff --git a/server/test/services/ScuntGameSettingsServices.test.js b/server/test/services/ScuntGameSettingsServices.test.js new file mode 100644 index 00000000..510b2237 --- /dev/null +++ b/server/test/services/ScuntGameSettingsServices.test.js @@ -0,0 +1,131 @@ +/* eslint-disable no-undef */ +const ScuntGameSettingsServices = require('../../src/services/ScuntGameSettingsServices'); +const assert = require('assert'); + +describe('ScuntGameSettingsServices', () => { + let settings; + + it('.setGameSettings()\t\t\t|\tSet invalid scunt game settings (SETTINGS_NOT_FOUND)', async () => { + await assert.rejects( + ScuntGameSettingsServices.setGameSettings( + 'Scunt2T3', + 11, + 2500, + 0.3, + true, + true, + true, + true, + 'url', + true, + true, + true, + ), + { + name: 'Error', + message: 'SETTINGS_NOT_FOUND', + }, + ); + }); + + it('.initScuntGameSettings()\t\t\t|\tFind settings', async () => { + settings = await ScuntGameSettingsServices.initScuntGameSettings(); + assert(settings.name === 'Scunt 2T3 Settings'); + assert(settings.amountOfTeams === 10); + }); + + /* couldn't think of test case for getGameSettings for it not to work besides network error */ + it('.getGameSettings()\t\t\t|\tGet scunt game settings', async () => { + settings = await ScuntGameSettingsServices.getGameSettings(); + assert(settings !== null); + assert.equal(settings.name, 'Scunt 2T3 Settings'); + assert.equal(settings.amountOfStarterBribePoints, 10000); + }); + + it('.setGameSettings()\t\t\t|\tSet scunt game settings', async () => { + settings = await ScuntGameSettingsServices.setGameSettings( + 'Scunt2T3 Settings', + 11, + 2500, + 0.3, + 0.3, + true, + true, + true, + true, + true, + true, + ); + assert(settings.name === 'Scunt2T3 Settings'); + assert(settings.amountOfTeams === 11); + }); + + it('.setGameSettings()\t\t\t|\tSet multiple scunt game settings', async () => { + await ScuntGameSettingsServices.setGameSettings( + 'Scunt2T3 Settings', + 11, + 2500, + 0.3, + 0.3, + true, + true, + true, + true, + true, + true, + ); + await ScuntGameSettingsServices.setGameSettings( + 'Scunt2T3 Settings', + 10, + 2500, + 0.3, + 0.3, + true, + true, + true, + true, + true, + true, + ); + await ScuntGameSettingsServices.setGameSettings( + 'Scunt2T3 Settings', + 11, + 2500, + 0.3, + 0.3, + true, + true, + false, + true, + true, + true, + ); + const testSettings = await ScuntGameSettingsServices.setGameSettings( + 'Scunt2T3 Settings', + 11, + 2400, + 0.3, + 0.3, + false, + true, + false, + true, + false, + true, + ); + assert(testSettings.amountOfStarterBribePoints === 2400); + await ScuntGameSettingsServices.setGameSettings( + 'Scunt2T3 Settings', + 10, + 2500, + 0.3, + 0.3, + true, + true, + true, + true, + true, + true, + ); + }); +}); diff --git a/server/test/services/ScuntMissionServices.test.js b/server/test/services/ScuntMissionServices.test.js new file mode 100644 index 00000000..03c86aa7 --- /dev/null +++ b/server/test/services/ScuntMissionServices.test.js @@ -0,0 +1,187 @@ +/* eslint-disable no-undef */ +const ScuntMissionServices = require('../../src/services/ScuntMissionServices'); +const LeadurModel = require('../../src/models/LeadurModel'); +const ScuntGameSettingModel = require('../../src/models/ScuntGameSettingsModel'); +const ScuntGameSettingsServices = require('../../src/services/ScuntGameSettingsServices'); +const assert = require('assert'); + +describe('ScuntMissionServices', () => { + let scuntMissions; + let leadur; + it('create(number, name, category, points, isHidden, isJudgingStation)\t\t\t\t|\tCreating A Scunt Mission', async () => { + const newMission = await ScuntMissionServices.create( + 1, + 'New Mission 1', + 'Category 1', + 10, + true, + true, + ); + assert(newMission.name === 'New Mission 1'); + }); + + it('create(number, name, category, points, isHidden, isJudgingStation)\t\t\t\t|\tCreating A Scunt Mission (INVALID MISSION)', async () => { + await assert.rejects(ScuntMissionServices.create(2, '', 'Category 1', 10, true, true), { + name: 'Error', + message: 'UNABLE_TO_CREATE_MISSION', + }); + }); + + it('create(number, name, category, points, isHidden, isJudgingStation)\t\t\t\t|\tCreating A Scunt Mission (ALREADY EXIST #)', async () => { + await assert.rejects( + ScuntMissionServices.create(1, 'New Mission 1', 'Category 1', 10, true, true), + { + name: 'Error', + message: 'UNABLE_TO_CREATE_MISSION', + }, + ); + }); + + it('.getAllScuntMissions(showHidden, user)\t\t\t\t\t\t\t\t|\tGetting Scunt Missions (NO SETTINGS)', async () => { + ScuntGameSettingModel.collection.drop(); + leadur = await LeadurModel.create({ + lastName: 'aaa', + firstName: 'aaa', + approved: true, + hashedPassword: 'aaa', + email: 'aaa@a.com', + authScopes: { + approved: ['scunt:exec show missions'], + }, + froshDataFields: {}, + }); + await assert.rejects(ScuntMissionServices.getAllScuntMissions(true, leadur), { + name: 'Error', + message: 'INVALID_SETTINGS', + }); + }); + + it('.getAllScuntMissions(showHidden, user)\t\t\t\t\t\t\t\t|\tGetting Scunt Missions', async () => { + const scuntGameSettings = { + name: 'Scunt 2T3 Settings', + amountOfTeams: 10, + amountOfStarterBribePoints: 10000, + maxAmountPointsPercent: 0.3, + minAmountPointsPercent: 0.3, + revealJudgesAndBribes: true, + revealTeams: true, + showDiscordLink: true, + discordLink: 'https://discord.gg/mRutbwuCK9', + revealLeaderboard: true, + revealMissions: true, + allowJudging: true, + }; + await ScuntGameSettingsServices.initScuntGameSettings(scuntGameSettings); + scuntMissions = await ScuntMissionServices.getAllScuntMissions(true, leadur); + + assert(scuntMissions[0].name === 'New Mission 1'); + }); + + it('createMultipleMissions(array)\t\t\t\t\t\t\t\t\t|\tCreating Multiple Scunt Missions (INVALID MISSION)', async () => { + const incorrectArray = [ + { + number: 1, + name: '', + category: 'Category 1', + points: 10, + isHidden: 'true', + isJudgingStation: 'true', + }, + ]; + await assert.rejects(ScuntMissionServices.createMultipleMissions(incorrectArray), { + name: 'Error', + message: 'UNABLE_TO_CREATE_SCUNT_MISSIONS', + }); + }); + + let array; + it('createMultipleMissions(array)\t\t\t\t\t\t\t\t\t|\tCreating Multiple Scunt Missions', async () => { + array = [ + { + number: 2, + name: 'New Mission 2', + category: 'Category 2', + points: 20, + isHidden: true, + isJudgingStation: true, + }, + { + number: 1, + name: 'New Mission 1', + category: 'Category 1', + points: 10, + isHidden: true, + isJudgingStation: true, + }, + { + number: 3, + name: 'New Mission 3', + category: 'Category 3', + points: 30, + isHidden: true, + isJudgingStation: true, + }, + ]; + const scuntMissions = await ScuntMissionServices.createMultipleMissions(array); + assert(scuntMissions[2].name === 'New Mission 3'); + }); + + it('.getAllScuntMissions(showHidden, user)\t\t\t\t\t\t\t\t|\tGetting Scunt Missions check sorting', async () => { + scuntMissions = await ScuntMissionServices.getAllScuntMissions(true, leadur); + + assert(scuntMissions[0].name === 'New Mission 1'); + assert(scuntMissions[1].name === 'New Mission 2'); + assert(scuntMissions[2].name === 'New Mission 3'); + }); + + it('updateMissionVisibility(startMissionNumber, endMissionNumber, isHidden, isJudgingStation)\t\t|\tUpdating Mission Visibility', async () => { + const missions = await ScuntMissionServices.updateMissionVisibility(1, 3, false, false); + assert(missions.modifiedCount === 3); + }); + + it('updateMissionVisibility(startMissionNumber, endMissionNumber, isHidden, isJudgingStation)\t\t|\tUpdating Mission Visibility (NO MISSIONS FOUND)', async () => { + await assert.rejects(ScuntMissionServices.updateMissionVisibility(11, 12, true, true), { + name: 'Error', + message: 'NO_MISSIONS_FOUND', + }); + }); + + it('updateMissionVisibility(startMissionNumber, endMissionNumber, isHidden, isJudgingStation)\t\t|\tUpdating Mission Visibility (INCORRECT PARAMETER)', async () => { + await assert.rejects(ScuntMissionServices.updateMissionVisibility(10, 20, 9999, true), { + name: 'Error', + message: 'UNABLE_TO_UPDATE_MISSION_VISIBILITY', + }); + }); + + it('deleteMission(number)\t\t\t\t\t\t\t\t\t\t|\tDeleting a Scunt Mission', async () => { + const deletedMission = await ScuntMissionServices.deleteMission(1); + assert(deletedMission.name === 'New Mission 1'); + }); + + it('deleteMission(number)\t\t\t\t\t\t\t\t\t\t|\tDeleting a Scunt Mission (INVALID INPUT)', async () => { + await assert.rejects(ScuntMissionServices.deleteMission('aaa'), { + name: 'Error', + message: 'UNABLE_TO_DELETE_MISSION', + }); + }); + + it('getMission(number)\t\t\t\t\t\t\t\t\t\t|\tGetting a Scunt Mission', async () => { + const mission = await ScuntMissionServices.getMission(2); + assert(mission.name === 'New Mission 2'); + }); + + it('getMission(number)\t\t\t\t\t\t\t\t\t\t|\tGetting a Scunt Mission (NONEXISTING MISSION)', async () => { + await assert.rejects(ScuntMissionServices.getMission(10), { + name: 'Error', + message: 'MISSION_NOT_FOUND', + }); + }); + + //idk if this is work + it('getMission(number)\t\t\t\t\t\t\t\t\t\t|\tGetting a Scunt Mission (INVALID PARAMETER)', async () => { + await assert.rejects(ScuntMissionServices.getMission('aaaa'), { + name: 'Error', + message: 'UNABLE_TO_GET_MISSION', + }); + }); +}); diff --git a/server/test/services/ScuntTeamServices.test.js b/server/test/services/ScuntTeamServices.test.js new file mode 100644 index 00000000..c5519867 --- /dev/null +++ b/server/test/services/ScuntTeamServices.test.js @@ -0,0 +1,565 @@ +/* eslint-disable no-undef */ +const ScuntTeamServices = require('../../src/services/ScuntTeamServices'); +const ScuntGameSettingsServices = require('../../src/services/ScuntGameSettingsServices'); +const LeadurModel = require('../../src/models/LeadurModel'); +const UserModel = require('../../src/models/UserModel'); +const ScuntTeamModel = require('../../src/models/ScuntTeamModel'); +const ScuntMissionModel = require('../../src/models/ScuntMissionModel'); +const ScuntGameSettingModel = require('../../src/models/ScuntGameSettingsModel'); +const assert = require('assert'); +const FroshModel = require('../../src/models/FroshModel'); + +describe('ScuntTeamServices', () => { + let testLeadur; + let team; + let teamPoints = []; + let teams = []; + let scuntJudges = []; + let tranactions = []; + + it('.getTeams()\t\t\t|\tShould return array with teams (NO TEAMS)', async () => { + await assert.rejects(ScuntTeamServices.getTeams(), { + name: 'Error', + message: 'TEAMS_NOT_FOUND', + }); + }); + + it('.viewRecentTransactions()\t\t|\tView recent transactions (empty)', async () => { + await assert.rejects(ScuntTeamServices.viewRecentTransactions(), { + name: 'Error', + message: 'TRANSACTIONS_NOT_FOUND', + }); + }); + + it('.updateLeaderTeam()\t\t|\tUpdate a leaders scunt team number', async () => { + const leadur = await LeadurModel.create({ + lastName: 'Testing', + firstName: 'Test', + approved: true, + hashedPassword: 'test12345', + email: 'test01@test.utoronto.ca', + froshDataFields: {}, + scuntTeam: 1, + }); + testLeadur = await ScuntTeamServices.updateLeaderTeam(leadur._id, 2); + assert(testLeadur.scuntTeam === 2); + }); + + it('.updateLeaderTeam()\t\t|\tUpdate a leaders scunt team number with wrong ID (UNABLE TO UPDATE LEADER)', async () => { + await assert.rejects(ScuntTeamServices.updateLeaderTeam(' ', 3), { + name: 'Error', + message: 'UNABLE_TO_UPDATE_LEADER', + }); + }); + + it('.updateLeaderTeam()\t\t|\tUpdate a non-leaders scunt team number (LEADUR_NOT_FOUND)', async () => { + testUser = await UserModel.create({ + firstName: 'Test', + lastName: 'User', + email: 'test2@test.utoronto.ca', + hashedPassword: 'test', + }); + await assert.rejects(ScuntTeamServices.updateLeaderTeam(testUser._id, 3), { + name: 'Error', + message: 'LEADUR_NOT_FOUND', + }); + }); + + it('.getTeamPoints()\t\t\t|\tShould return array with teams and their points', async () => { + await assert.rejects(ScuntTeamServices.getTeamPoints(), { + name: 'Error', + message: 'TEAMS_NOT_FOUND', + }); + }); + + it('.getTeamPoints()\t\t\t|\tShould return array with teams and their points', async () => { + await ScuntTeamModel.create({ + name: 'Test Team', + points: 10, + }); + teamPoints = await ScuntTeamServices.getTeamPoints(); + assert(teamPoints.length === 1); + }); + + it('.getTeams()\t\t\t|\tShould return array with teams', async () => { + teams = await ScuntTeamServices.getTeams(); + assert(teams.length > 0); + }); + + it('.bribeTransaction()\t\t|\tUpdate a bribe transaction (INVALID_SETTINGS)', async () => { + await ScuntGameSettingModel.collection.drop(); + await assert.rejects( + ScuntTeamServices.bribeTransaction(8, 10, { scuntJudgeBribePoints: 10000 }), + { + name: 'Error', + message: 'INVALID_SETTINGS', + }, + ); + }); + + it('.bribeTransaction()\t\t|\tUpdate a bribe transaction (NOT_ALLOWED_TO_JUDGE)', async () => { + await ScuntGameSettingModel.findOneAndUpdate( + {}, + { $set: { allowJudging: false } }, + { upsert: true }, + ); + await assert.rejects( + ScuntTeamServices.bribeTransaction(8, 10, { scuntJudgeBribePoints: 10000 }), + { + name: 'Error', + message: 'NOT_ALLOWED_TO_JUDGE', + }, + ); + ScuntGameSettingModel.collection.drop(); + }); + + it('.bribeTransaction()\t\t|\tUpdate a bribe transaction (LEADUR_NOT_FOUND)', async () => { + await ScuntGameSettingModel.findOneAndUpdate( + {}, + { $set: { allowJudging: true } }, + { upsert: true }, + ); + await assert.rejects( + ScuntTeamServices.bribeTransaction(8, 10, { scuntJudgeBribePoints: 10000 }), + { + name: 'Error', + message: 'LEADUR_NOT_FOUND', + }, + ); + ScuntGameSettingModel.collection.drop(); + }); + + it('.bribeTransaction()\t\t|\tUpdate a bribe transaction', async () => { + await ScuntGameSettingModel.findOneAndUpdate( + {}, + { $set: { allowJudging: true } }, + { upsert: true }, + ); + const leadur = await LeadurModel.create({ + lastName: 'Testerson', + firstName: 'Test', + approved: true, + hashedPassword: 'test12345', + email: 'test3@test.utoronto.ca', + froshDataFields: {}, + scuntTeam: 1, + scuntJudgeBribePoints: 2000, + }); + + await ScuntTeamModel.create({ + number: 8, + name: 'Scunt Team 8', + points: 20, + }); + + const { testLeadur } = await ScuntTeamServices.bribeTransaction(8, 10, leadur); + assert(testLeadur !== null); + }); + + it('.bribeTransaction()\t\t|\tUpdate a bribe transaction (NOT ENOUGH BRIBE POINTS)', async () => { + const leadur = await LeadurModel.create({ + lastName: 'Testerson', + firstName: 'Test', + approved: true, + hashedPassword: 'test12345', + email: 'test4@test.utoronto.ca', + froshDataFields: {}, + scuntTeam: 1, + scuntJudgeBribePoints: 1, + }); + await assert.rejects(ScuntTeamServices.bribeTransaction(8, 3000, leadur), { + name: 'Error', + message: 'NOT_ENOUGH_BRIBE_POINTS', + }); + }); + + it('.bribeTransaction()\t\t|\tUpdate a bribe transaction (INVALID_TEAM_NUMBER)', async () => { + const leadur = await LeadurModel.create({ + lastName: 'Testerson', + firstName: 'Test', + approved: true, + hashedPassword: 'test12345', + email: 'test4@t43534est.utoronto.ca', + froshDataFields: {}, + scuntTeam: 1, + scuntJudgeBribePoints: 1000000, + }); + await assert.rejects(ScuntTeamServices.bribeTransaction(1200, 3000, leadur), { + name: 'Error', + message: 'INVALID_TEAM_NUMBER', + }); + }); + + it('.bribeTransaction()\t\t|\tUpdate a bribe transaction (UNABLE_TO_UPDATE_TEAM)', async () => { + const leadur = await LeadurModel.create({ + lastName: 'Testerson', + firstName: 'Test', + approved: true, + hashedPassword: 'test12345', + email: 'test4@t4355345534est.utoronto.ca', + froshDataFields: {}, + scuntTeam: 1, + scuntJudgeBribePoints: 1000000, + }); + await assert.rejects(ScuntTeamServices.bribeTransaction('dfsdf', 3000, leadur), { + name: 'Error', + message: 'UNABLE_TO_UPDATE_TEAM', + }); + }); + + it('.getScuntJudges()\t\t\t|\tShould return array with scunt judges', async () => { + await assert.rejects(ScuntTeamServices.getScuntJudges(), { + name: 'Error', + message: 'JUDGES_NOT_FOUND', + }); + }); + + it('.getScuntJudges()\t\t\t|\tShould return array with scunt judges', async () => { + await LeadurModel.create({ + lastName: 'Testersen', + firstName: 'Test', + approved: true, + hashedPassword: 'test12345', + email: 'test14@test.utoronto.ca', + froshDataFields: {}, + scuntTeam: 1, + authScopes: { + approved: ['scunt:judge bribe points'], + }, + scuntJudgeBribePoints: 20, + }); + const judges = await ScuntTeamServices.getScuntJudges(); + assert(judges.length === 1); + }); + + it('.refillBribePoints()\t\t|\tRefill judge bribe points', async () => { + const leadur = await LeadurModel.create({ + lastName: 'Testerson', + firstName: 'Test', + approved: true, + hashedPassword: 'test12345', + email: 'test6@test.utoronto.ca', + froshDataFields: {}, + scuntTeam: 1, + scuntJudgeBribePoints: 20, + }); + const refilledleadur = await ScuntTeamServices.refillBribePoints(leadur._id, 10, true); + assert(refilledleadur.scuntJudgeBribePoints === 30); + }); + + it('.refillBribePoints()\t\t|\tRefill judge bribe points', async () => { + const leadur = await LeadurModel.create({ + lastName: 'Testerson', + firstName: 'Test', + approved: true, + hashedPassword: 'test12345', + email: 'test7@test.utoronto.ca', + froshDataFields: {}, + scuntTeam: 1, + scuntJudgeBribePoints: 20, + }); + const refilledleadur = await ScuntTeamServices.refillBribePoints(leadur._id, 10, false); + assert(refilledleadur.scuntJudgeBribePoints === 10); + }); + + it('.refillBribePoints()\t\t|\tRefill judge bribe points with wrong ID (UNABLE TO UPDATE LEADUR)', async () => { + await assert.rejects(ScuntTeamServices.refillBribePoints('1234567890', 10, true), { + name: 'Error', + message: 'UNABLE_TO_UPDATE_LEADUR', + }); + }); + + it('.refillBribePoints()\t\t|\tRefill judge bribe points with wrong ID (LEADUR_NOT_FOUND)', async () => { + testUser = await UserModel.create({ + firstName: 'Test', + lastName: 'User', + email: 'test8@test.utoronto.ca', + hashedPassword: 'test', + }); + await assert.rejects(ScuntTeamServices.refillBribePoints(testUser._id, 10, true), { + name: 'Error', + message: 'LEADUR_NOT_FOUND', + }); + }); + + it('.addTransaction()\t\t\t|\tAdd transaction', async () => { + await ScuntGameSettingsServices.initScuntGameSettings(); + await ScuntTeamModel.create({ + number: 1, + name: 'Scunt Team 1', + points: 0, + }); + const testTeamTransaction = await ScuntTeamServices.addTransaction(1, 2, 20); + assert.equal(testTeamTransaction, 'Added 20 points for mission #2 for team 1'); + }); + + it('.addTransaction()\t\t\t|\tAdd transaction same mission', async () => { + const testTeamTransaction = await ScuntTeamServices.addTransaction(1, 2, 200); + assert.equal(testTeamTransaction, 'Updated to 200 points for mission #2 for team 1'); + }); + + it('.addTransaction()\t\t\t|\tAdd transaction same mission', async () => { + const testTeamTransaction = await ScuntTeamServices.addTransaction(1, 2, 10); + assert.equal(testTeamTransaction, '10 points for mission #2 for team 1'); + }); + + it('.addTransaction()\t\t\t|\tAdd transaction', async () => { + await ScuntTeamModel.create({ + number: 9, + name: 'Scunt Team 9', + points: 20, + }); + const testTeamTransaction = await ScuntTeamServices.addTransaction(9, 2, 30); + assert.equal(testTeamTransaction, 'Added 30 points for mission #2 for team 9'); + }); + + // having trouble with prev points with addTransaction + + it('.addTransaction()\t\t\t|\tAdd transaction (INVALID_SETTINGS)', async () => { + await ScuntGameSettingModel.collection.drop(); + await assert.rejects(ScuntTeamServices.addTransaction(100000, 2, 20), { + name: 'Error', + message: 'INVALID_SETTINGS', + }); + await ScuntGameSettingModel.findOneAndUpdate( + {}, + { $set: { allowJudging: true } }, + { upsert: true }, + ); + }); + + it('.addTransaction()\t\t\t|\tAdd transaction (NOT_ALLOWED_TO_JUDGE)', async () => { + await ScuntGameSettingModel.findOneAndUpdate( + {}, + { $set: { allowJudging: false } }, + { upsert: true }, + ); + await assert.rejects(ScuntTeamServices.addTransaction(100000, 2, 20), { + name: 'Error', + message: 'NOT_ALLOWED_TO_JUDGE', + }); + await ScuntGameSettingModel.findOneAndUpdate( + {}, + { $set: { allowJudging: true } }, + { upsert: true }, + ); + }); + + it('.addTransaction()\t\t\t|\tAdd transaction (INVALID TEAM)', async () => { + await assert.rejects(ScuntTeamServices.addTransaction(100000, 2, 20), { + name: 'Error', + message: 'INVALID_TEAM_NUMBER', + }); + }); + + it('.subtractTransaction()\t\t|\tSubtract transaction', async () => { + await ScuntTeamModel.create({ + number: 2, + name: 'Scunt Team 2', + points: 20, + }); + const testTeam = await ScuntTeamServices.subtractTransaction(2, 20); + assert(testTeam.points === 0); + }); + + it('.subtractTransaction()\t\t|\tSubtract transaction', async () => { + await ScuntTeamModel.create({ + number: 10, + name: 'Scunt Team 10', + points: 10, + }); + const testTeam = await ScuntTeamServices.subtractTransaction(10, 20); + assert(testTeam.points === -10); + }); + + it('.subtractTransaction()\t\t|\tSubtract transaction (INVALID TEAM)', async () => { + await assert.rejects(ScuntTeamServices.subtractTransaction(100000, 20), { + name: 'Error', + message: 'INVALID_TEAM_NUMBER', + }); + }); + + it('.viewTransactions()\t\t|\tView transactions', async () => { + await ScuntTeamServices.subtractTransaction(10, 20); + await ScuntTeamServices.subtractTransaction(10, 20); + await ScuntTeamServices.subtractTransaction(10, 20); + const transactions = await ScuntTeamServices.viewTransactions(10); + assert.equal(transactions.length, 4); + }); + + it('.viewTransactions()\t\t|\tView transactions (INVALID TEAM)', async () => { + await assert.rejects(ScuntTeamServices.viewTransactions(100000), { + name: 'Error', + message: 'INVALID_TEAM_NUMBER', + }); + }); + + it('.checkTransaction()\t\t|\tCheck a transaction', async () => { + await ScuntTeamModel.create({ + number: 4, + name: 'Scunt Team 4', + points: 10, + }); + await ScuntMissionModel.create({ + number: 1, + name: 'Test Mission', + category: '', + points: 10, + isHidden: false, + isJudgingStation: false, + }); + const points = await ScuntTeamServices.checkTransaction(4, 1); + assert.equal(points, 0); + }); + + it('.checkTransaction()\t\t|\tCheck a transaction', async () => { + await ScuntTeamServices.addTransaction(4, 1, 20); + await ScuntTeamServices.addTransaction(4, 1, 10); + const points = await ScuntTeamServices.checkTransaction(4, 1); + assert.equal(points, 14); + }); + + it('.checkTransaction()\t\t|\tCheck a transaction (INVALID TEAM NUMBER)', async () => { + await assert.rejects(ScuntTeamServices.checkTransaction(1000, 10), { + name: 'Error', + message: 'INVALID_TEAM_NUMBER', + }); + }); + + it('.initializeTeams()\t\t|\tInitialize scunt teams (INVALID_SETTINGS)', async () => { + await ScuntGameSettingModel.collection.drop(); + await assert.rejects(ScuntTeamServices.initializeTeams(), { + name: 'Error', + message: 'INVALID_SETTINGS', + }); + }); + + it('.initializeTeams()\t\t|\tInitialize scunt teams (MISSING_SCUNT_SETTINGS)', async () => { + await ScuntGameSettingModel.findOneAndUpdate( + {}, + { $set: { amountOfTeams: null } }, + { upsert: true }, + ); + await assert.rejects(ScuntTeamServices.initializeTeams(), { + name: 'Error', + message: 'MISSING_SCUNT_SETTINGS', + }); + await ScuntGameSettingModel.collection.drop(); + await ScuntGameSettingModel.findOneAndUpdate( + {}, + { $set: { allowJudging: true, amountOfTeams: 10 } }, + { upsert: true }, + ); + }); + + it('.initializeTeams()\t\t|\tInitialize scunt teams (SCUNT_FROSH_NOT_FOUND)', async () => { + await ScuntTeamModel.collection.drop(); + await FroshModel.collection.drop(); + await assert.rejects(ScuntTeamServices.initializeTeams(), { + name: 'Error', + message: 'SCUNT_FROSH_NOT_FOUND', + }); + }); + + it('.initializeTeams()\t\t|\tInitialize scunt teams', async () => { + await ScuntTeamModel.collection.drop(); + for (let i = 0; i < 10; i += 1) { + await FroshModel.create({ + scuntPreferredMembers: [1, 2, 3].includes(i) + ? ['test1@test.com', 'test2@test.com', 'test3@test.com'] + : i === 4 + ? ['fdfgdfgdfgdfgdfgdfgdfgdf', 'test1@test.com', 'test2@test.com'] + : i === 5 + ? ['test4@test.com', 'test2@test.com', 'test3@test.com'] + : [], + hashedPassword: 'test', + firstName: `Test ${i}`, + lastName: `Test ${i}`, + email: `test${i}@test.com`, + legalName: `Test ${i}`, + pronouns: 'Other', + birthDate: new Date(), + utorid: 'test123', + discipline: 'Chemical', + shirtSize: 'L', + phoneNumber: '123456', + emergencyContactName: 'test', + emergencyContactRelationship: 'test', + emergencyContactNumber: 'test', + bursaryRequested: false, + attendingScunt: true, + summerLocationCity: 'test', + summerLocationCountry: 'test', + photograph: true, + froshGroup: 'test', + isRegistered: true, + froshGroupIcon: 'test', + scuntTeam: 0, + }); + } + await ScuntTeamServices.initializeTeams(); + }); + + it('.deleteTransaction()\t\t|\tDelete a transaction', async () => { + const scuntTeam = await ScuntTeamModel.create({ + number: 11, + name: 'Scunt Team 11', + points: 10, + }); + await ScuntMissionModel.create({ + number: 200, + name: 'Test Mission 2', + category: '', + points: 10, + isHidden: false, + isJudgingStation: false, + }); + scuntTeam.transactions = []; + scuntTeam.transactions.push({ _id: 4545345, name: 'Test', points: 5, missionNumber: 2 }); + const testTeam = await ScuntTeamServices.deleteTransaction(11, 4545345); + assert(testTeam.transactions.length === 0); + }); + + it('.deleteTransaction()\t\t|\tDelete a transaction (INVALID TEAM NUMBER)', async () => { + await assert.rejects(ScuntTeamServices.deleteTransaction(100000, 429496729), { + name: 'Error', + message: 'TEAM_NOT_FOUND', + }); + }); + + it('.viewRecentTransactions()\t\t|\tView recent transactions', async () => { + await ScuntTeamModel.create({ + number: 16, + name: 'Scunt Team 16', + points: 10, + }); + await ScuntMissionModel.create({ + number: 30, + name: 'Test Mission 3', + category: '', + points: 10, + isHidden: false, + isJudgingStation: false, + }); + await ScuntTeamServices.addTransaction(16, 3, 10); + transactions = await ScuntTeamServices.viewRecentTransactions(); + assert(transactions.length > 0); + }); + + it('.setTeamName()\t\t\t|\tSet new team name', async () => { + await ScuntTeamModel.create({ + number: 17, + name: 'Scunt Team 17', + points: 20, + }); + const testTeam = await ScuntTeamServices.setTeamName(17, 'Scunt Team 17'); + assert(testTeam.name === 'Scunt Team 17'); + }); + + it('.setTeamName()\t\t\t|\tSet invalid team name (INVALID NUMBER)', async () => { + await assert.rejects(ScuntTeamServices.setTeamName(100000, 'lalalalalala'), { + name: 'Error', + message: 'INVALID_TEAM_NUMBER', + }); + }); +}); diff --git a/server/test/services/TimelineServices.test.js b/server/test/services/TimelineServices.test.js new file mode 100644 index 00000000..93b3c69a --- /dev/null +++ b/server/test/services/TimelineServices.test.js @@ -0,0 +1,93 @@ +/* eslint-disable no-undef */ +const TimelineServices = require('../../src/services/TimelineServices'); +const assert = require('assert'); + +describe('TimelineServices', () => { + let createdTimeline; + it('.create()', async () => { + createdTimeline = await TimelineServices.create( + new Date(), + 'Test Event', + 'Test Description', + 'Test Link', + 'Test Link Label', + ); + assert.equal(createdTimeline.eventName, 'Test Event'); + assert.equal(createdTimeline.description, 'Test Description'); + assert.equal(createdTimeline.link, 'Test Link'); + assert.equal(createdTimeline.linkLabel, 'Test Link Label'); + }); + + it('.getAll()', async () => { + const timelines = await TimelineServices.getAll(); + assert.equal(timelines.length, 1); + }); + + it('.update()', async () => { + const updatedTimeline = await TimelineServices.update( + createdTimeline._id, + new Date(), + 'Test Event Updated', + 'Test Description Updated', + 'Test Link Updated', + 'Test Link Label Updated', + ); + assert.equal(updatedTimeline.eventName, 'Test Event Updated'); + assert.equal(updatedTimeline.description, 'Test Description Updated'); + assert.equal(updatedTimeline.link, 'Test Link Updated'); + assert.equal(updatedTimeline.linkLabel, 'Test Link Label Updated'); + }); + + it('.update() invalid id', async () => { + await assert.rejects( + TimelineServices.update( + 'createdTimeline._id', + new Date(), + 'Test Event Updated', + 'Test Description Updated', + 'Test Link Updated', + 'Test Link Label Updated', + ), + { + name: 'Error', + message: 'UNABLE_TO_UPDATE_TIMELINE', + }, + ); + }); + + it('.update() no timeline', async () => { + await assert.rejects( + TimelineServices.update( + '353b24b4b4b4b4b4b4b4b4b4', + new Date(), + 'Test Event Updated', + 'Test Description Updated', + 'Test Link Updated', + 'Test Link Label Updated', + ), + { + name: 'Error', + message: 'TIMELINE_NOT_FOUND', + }, + ); + }); + + it('.delete(id)', async () => { + const timeline = await TimelineServices.delete(createdTimeline._id); + assert.equal(timeline.id, createdTimeline.id); + }); + + it('.delete(id) invalid id', async () => { + await assert.rejects(TimelineServices.delete('createdTimeline._id'), { + name: 'Error', + message: 'UNABLE_TO_DELETE_TIMELINE', + }); + }); + + it('.delete(id) no timeline', async () => { + await assert.rejects(TimelineServices.delete('353b24b4b4b4b4b4b4b4b4b4'), { + name: 'Error', + message: 'TIMELINE_NOT_FOUND', + }); + }); +}); diff --git a/server/test/services/UserServices.test.js b/server/test/services/UserServices.test.js new file mode 100644 index 00000000..ddad7383 --- /dev/null +++ b/server/test/services/UserServices.test.js @@ -0,0 +1,458 @@ +/* eslint-disable no-undef */ +const UserServices = require('../../src/services/UserServices'); +const UserModel = require('../../src/models/UserModel'); +const jwt = require('jsonwebtoken'); +const assert = require('assert'); +const LeadurModel = require('../../src/models/LeadurModel'); + +describe('UserServices', () => { + process.env.JWT_RESET_TOKEN = 123; + process.env.JWT_EMAIL_CONFIRMATION_TOKEN = 123; + + let testUser1; + let testUser2; + + it('.validateUser(email, password)', async () => { + await UserServices.validateUser('test@validate.com', 'Password!23'); + }); + + it('.validateUser(email, password) Invalid password', async () => { + await assert.rejects(UserServices.validateUser('test@validateInvalid.com', 'Password!'), { + name: 'Error', + message: 'INVALID_PASSWORD', + }); + }); + + it('.validateUser(email, password) Invalid emails', async () => { + await assert.rejects(UserServices.validateUser('fdsdsfs', 'Password!'), { + name: 'Error', + message: 'INVALID_EMAIL', + }); + }); + + it('.validateUser(email, password) Duplicate emails', async () => { + testUser1 = await UserModel.create({ + email: 'test@test.com', + hashedPassword: '$2b$1', + firstName: 'Test', + lastName: 'User', + }); + await assert.rejects(UserServices.validateUser('test@test.com', 'Password!2'), { + name: 'Error', + message: 'DUPLICATE_EMAIL', + }); + }); + + it('.create(email, password, firstName, lastName, preferredName)', async () => { + testUser2 = await UserServices.create('test@create.com', 'Password!23', 'Test', 'User', 'Test'); + + assert.equal(testUser2.email, 'test@create.com'); + assert.equal(testUser2.firstName, 'Test'); + assert.equal(testUser2.lastName, 'User'); + assert.equal(testUser2.preferredName, 'Test'); + }); + + it('.create(...) Invalid password', async () => { + await assert.rejects(UserServices.create('test@create1.com', null, 'Test', 'User', 'Test'), { + name: 'Error', + message: 'UNABLE_TO_HASH_PASSWORD', + }); + }); + + it('.create(...) Invalid name', async () => { + await assert.rejects( + UserServices.create('test@create2.com', 'Password!23', '', 'User', 'Test'), + { + name: 'Error', + message: 'UNABLE_TO_CREATE_USER', + }, + ); + }); + + let passwordResetToken; + it('.generatePasswordResetToken(email)', async () => { + passwordResetToken = await UserServices.generatePasswordResetToken('test@test.com'); + assert(passwordResetToken); + }); + + it('.generatePasswordResetToken(email) Wrong email', async () => { + await assert.rejects(UserServices.generatePasswordResetToken('test@noemail.com'), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.generatePasswordResetToken(email) Invalid email', async () => { + await assert.rejects(UserServices.generatePasswordResetToken(), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.generatePasswordResetToken(email) bad environment', async () => { + const env = process.env; + delete env.JWT_RESET_TOKEN; + await assert.rejects(UserServices.generatePasswordResetToken('test@test.com'), { + name: 'Error', + message: 'UNABLE_TO_GENERATE_PASSWORD_RESET_TOKEN', + }); + }); + + it('.validatePasswordResetToken(token)', async () => { + process.env.JWT_RESET_TOKEN = 123; + const result = await UserServices.validatePasswordResetToken(passwordResetToken); + assert.equal(result.userEmail, 'test@test.com'); + }); + + it('.validatePasswordResetToken(token) invalid token', async () => { + await assert.rejects(UserServices.validatePasswordResetToken('passwordResetToken'), { + name: 'Error', + message: 'UNABLE_TO_VALIDATE_PASSWORD_RESET_TOKEN', + }); + }); + + it('.checkScuntToken(existingUser) user with scunt token', async () => { + const result = await UserServices.checkScuntToken(testUser2); + assert.equal(result, true); + }); + + it('.checkScuntToken(existingUser) no scunt token', async () => { + const result = await UserServices.checkScuntToken({ name: 'test' }); + assert.equal(result, false); + }); + + it('.addScuntToken(userId) add scunt token', async () => { + const user = await UserServices.addScuntToken(testUser1._id); + assert(user.scuntToken); + }); + + it('.addScuntToken(userId) bad ID', async () => { + await assert.rejects(UserServices.addScuntToken('354b434b54b5'), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.validateEmailConfirmationToken(token)', async () => { + const token = jwt.sign('test@test.com', process.env.JWT_EMAIL_CONFIRMATION_TOKEN); + + const result = await UserServices.validateEmailConfirmationToken(token); + + assert.equal(result, 'test@test.com'); + }); + + it('.validateEmailConfirmationToken(token) invalid token', async () => { + await assert.rejects(UserServices.validateEmailConfirmationToken('passwordResetToken'), { + name: 'Error', + message: 'UNABLE_TO_VALIDATE_EMAIL_CONFIRMATION_TOKEN', + }); + }); + + it('.getUserByEmail(email) get a user from email', async () => { + const result = await UserServices.getUserByEmail('test@test.com'); + assert.equal(result.email, 'test@test.com'); + }); + + it('.getUserByEmail(email) invalid email', async () => { + await assert.rejects(UserServices.getUserByEmail('no@email.com'), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.getUserByID(userID) get a user from email', async () => { + const result = await UserServices.getUserByID(testUser2._id); + assert.equal(result.email, 'test@create.com'); + }); + + it('.getUserByID(userID) invalid id', async () => { + await assert.rejects(UserServices.getUserByID('noid'), { + name: 'Error', + message: 'UNABLE_TO_GET_USER', + }); + }); + + it('.getUserByID(userID) no user', async () => { + await assert.rejects(UserServices.getUserByID('23435b5456b6'), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.getAllUsers() Gets all users', async () => { + await UserModel.collection.drop(); + await UserModel.create({ + firstName: 'Test', + lastName: 'User', + email: 'test1', + hashedPassword: 'test', + }); + await UserModel.create({ + firstName: 'Test', + lastName: 'User', + email: 'test2', + hashedPassword: 'test', + }); + const result = await UserServices.getAllUsers(); + assert.equal(result.length, 2); + }); + + it('.getAllUsers() no users', async () => { + await UserModel.collection.drop(); + await assert.rejects(UserServices.getAllUsers(), { + name: 'Error', + message: 'USERS_NOT_FOUND', + }); + }); + + it('.updatePassword(email, password)', async () => { + await UserModel.create({ + email: 'test@test.com', + hashedPassword: '$2b$1', + firstName: 'Test', + lastName: 'User', + }); + testUser1 = await UserServices.updatePassword('test@test.com', 'Password!23'); + assert(testUser1.hashedPassword); + assert.notEqual(testUser1.hashedPassword, '$2b$1'); + }); + + it('.updatePassword(email, password) invalid email', async () => { + await assert.rejects(UserServices.updatePassword('no@email.com', 'Password!2'), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.updatePassword(email, password) invalid password', async () => { + await assert.rejects(UserServices.updatePassword('no@email.com', 'Password'), { + name: 'Error', + message: 'INVALID_PASSWORD', + }); + }); + + it('.getUsersAuthScopes() no leedurs', async () => { + await assert.rejects(UserServices.getUsersAuthScopes(), { + name: 'Error', + message: 'USERS_NOT_FOUND', + }); + }); + + it('.requestAuthScopes(user, scopes)', async () => { + const result = await UserServices.requestAuthScopes(testUser1.id, ['test']); + assert.equal(result.authScopes.requested[0], 'test'); + }); + + it('.requestAuthScopes(user, scopes) no user', async () => { + await assert.rejects(UserServices.requestAuthScopes('23435b5456b6', ['test']), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.requestAuthScopes(user, scopes) invalid id', async () => { + await assert.rejects(UserServices.requestAuthScopes('', ['test']), { + name: 'Error', + message: 'UNABLE_TO_UPDATE_AUTH_SCOPES_FOR_USER', + }); + }); + + it('.unsubscribeUser(email)', async () => { + const result = await UserServices.unsubscribeUser(testUser1.email); + assert.equal(result.canEmail, false); + }); + + it('.unsubscribeUser(email) no user', async () => { + await assert.rejects(UserServices.unsubscribeUser(' '), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.resubscribeUser(email)', async () => { + const result = await UserServices.resubscribeUser(testUser1.email); + assert.equal(result.canEmail, true); + }); + + it('.resubscribeUser(email) no user', async () => { + await assert.rejects(UserServices.resubscribeUser(' '), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.getUnapprovedUsers() no leedurs', async () => { + await assert.rejects(UserServices.getUnapprovedUsers(), { + name: 'Error', + message: 'USERS_NOT_FOUND', + }); + }); + + it('.getUnapprovedUsers()', async () => { + testUser1 = await LeadurModel.create({ + email: 'test@test.com', + hashedPassword: '$2b$1', + firstName: 'Test', + lastName: 'User', + approved: false, + }); + const result = await UserServices.getUnapprovedUsers(); + assert.equal(result.length, 1); + }); + + it('.getUsersAuthScopes()', async () => { + const result = await UserServices.getUsersAuthScopes(); + assert.equal(result.length, 1); + }); + + it('.approveAccountsByIds(accountIds)', async () => { + testUser1 = await LeadurModel.create({ + email: 'test@test123.com', + hashedPassword: '$2b$1', + firstName: 'Test', + lastName: 'User', + approved: false, + }); + const result = await UserServices.approveAccountsByIds([testUser1.id]); + assert.equal(result.matchedCount, 1); + }); + + it('.approveAccountsByIds(accountIds) invalid ids', async () => { + await assert.rejects(UserServices.approveAccountsByIds([testUser1.id, '23435b5456b6']), { + name: 'Error', + message: 'USERS_NOT_FOUND', + }); + }); + + it('.updateAuthScopes(userAuthScopes)', async () => { + const result = await UserServices.updateAuthScopes([ + { + id: testUser1.id, + auth: [ + { + approve: true, + isFroshData: true, + authreq: 'test', + }, + { + approve: true, + isFroshData: false, + authreq: 'test', + }, + { + approve: false, + isFroshData: true, + authreq: 'test1', + }, + { + approve: false, + isFroshData: false, + authreq: 'test2', + }, + ], + }, + ]); + assert.equal(result.modifiedCount, 1); + }); + + it('.updateAuthScopes(userAuthScopes) invalid id', async () => { + await assert.rejects( + UserServices.updateAuthScopes([ + { + id: testUser1.id, + auth: [ + { + approve: true, + isFroshData: true, + authreq: 'test', + }, + { + approve: true, + isFroshData: false, + authreq: 'test', + }, + { + approve: false, + isFroshData: true, + authreq: 'test1', + }, + { + approve: false, + isFroshData: false, + authreq: 'test2', + }, + ], + }, + ]), + { + name: 'Error', + message: 'USERS_NOT_FOUND', + }, + ); + }); + + it('.getScuntJudgeUsers() no users', async () => { + await assert.rejects(UserServices.getScuntJudgeUsers(), { + name: 'Error', + message: 'USERS_NOT_FOUND', + }); + }); + + it('.getScuntJudgeUsers()', async () => { + await LeadurModel.create({ + email: 'test@test123.com', + hashedPassword: '$2b$1', + firstName: 'Test', + lastName: 'User', + authScopes: { + approved: ['scunt:judge bribe points'], + }, + }); + const result = await UserServices.getScuntJudgeUsers(); + assert.equal(result.length, 1); + }); + + it('.updateUserInfo(userId, updateInfo)', async () => { + const user = await UserServices.updateUserInfo(testUser1.id, { + firstName: 'Test1', + lastName: 'User1', + email: 'update@user.com', + }); + assert.equal(user.firstName, 'Test1'); + assert.equal(user.lastName, 'User1'); + assert.equal(user.email, 'update@user.com'); + }); + + it('.updateUserInfo(userId, updateInfo) no user', async () => { + await assert.rejects(UserServices.updateUserInfo('23435b5456b6', { firstName: 'update' }), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.updateUserInfo(userId, updateInfo) invalid id', async () => { + await assert.rejects(UserServices.updateUserInfo('', { firstName: 'update' }), { + name: 'Error', + message: 'UNABLE_TO_UPDATE_USER', + }); + }); + + it('.deleteUser(id)', async () => { + const result = await UserServices.deleteUser(testUser1.id); + assert.equal(result.id, testUser1.id); + }); + + it('.deleteUser(id) no user', async () => { + await assert.rejects(UserServices.deleteUser('23435b5456b6'), { + name: 'Error', + message: 'USER_NOT_FOUND', + }); + }); + + it('.deleteUser(id) invalid id', async () => { + await assert.rejects(UserServices.deleteUser(''), { + name: 'Error', + message: 'UNABLE_TO_DELETE_USER', + }); + }); +}); diff --git a/server/yarn.lock b/server/yarn.lock index a22a98c9..20d41c4b 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -102,199 +102,157 @@ "@aws-sdk/util-utf8-browser" "^3.0.0" tslib "^1.11.1" -"@aws-sdk/client-cognito-identity@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.363.0.tgz#75c94c3ea4dd1ef3bd5fefab3bde69dd19dbbb38" - integrity sha512-tsJzgBSCpna85IVsuS7FBIK9wkSl7fs8TJ/QzapIgu8rKss0ySHVO6TeMVAdw2BvaQl7CxU9c3PosjhLWHu6KQ== - dependencies: - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.363.0" - "@aws-sdk/credential-provider-node" "3.363.0" - "@aws-sdk/middleware-host-header" "3.363.0" - "@aws-sdk/middleware-logger" "3.363.0" - "@aws-sdk/middleware-recursion-detection" "3.363.0" - "@aws-sdk/middleware-signing" "3.363.0" - "@aws-sdk/middleware-user-agent" "3.363.0" - "@aws-sdk/types" "3.357.0" - "@aws-sdk/util-endpoints" "3.357.0" - "@aws-sdk/util-user-agent-browser" "3.363.0" - "@aws-sdk/util-user-agent-node" "3.363.0" - "@smithy/config-resolver" "^1.0.1" - "@smithy/fetch-http-handler" "^1.0.1" - "@smithy/hash-node" "^1.0.1" - "@smithy/invalid-dependency" "^1.0.1" - "@smithy/middleware-content-length" "^1.0.1" - "@smithy/middleware-endpoint" "^1.0.1" - "@smithy/middleware-retry" "^1.0.2" - "@smithy/middleware-serde" "^1.0.1" - "@smithy/middleware-stack" "^1.0.1" - "@smithy/node-config-provider" "^1.0.1" - "@smithy/node-http-handler" "^1.0.2" - "@smithy/protocol-http" "^1.0.1" - "@smithy/smithy-client" "^1.0.3" - "@smithy/types" "^1.0.0" - "@smithy/url-parser" "^1.0.1" - "@smithy/util-base64" "^1.0.1" - "@smithy/util-body-length-browser" "^1.0.1" - "@smithy/util-body-length-node" "^1.0.1" - "@smithy/util-defaults-mode-browser" "^1.0.1" - "@smithy/util-defaults-mode-node" "^1.0.1" - "@smithy/util-retry" "^1.0.2" - "@smithy/util-utf8" "^1.0.1" - tslib "^2.5.0" - "@aws-sdk/client-sesv2@^3.100.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sesv2/-/client-sesv2-3.363.0.tgz#82136d8406e462c79c0f9bc22c6aa3fecfff7b71" - integrity sha512-4FbbVdZaDz/LlQJbVJaVI+6s4X08PdhOoWO4jIz5zwn7JxjU5Z533WM8Jf2BbS2NSCh9eb0OiUbdu/EnPO3juA== + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sesv2/-/client-sesv2-3.370.0.tgz#f16058e50a1688c380d76c0632f28c1fbf9b25ba" + integrity sha512-FehIk25U27DRKEnpu8e1jaLogom/eIfs1PgvN0H7IkdBooJC8Vi2pKI4pM5YzlhGB3A4IUmc8wwXqx/YLKlsqQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.363.0" - "@aws-sdk/credential-provider-node" "3.363.0" - "@aws-sdk/middleware-host-header" "3.363.0" - "@aws-sdk/middleware-logger" "3.363.0" - "@aws-sdk/middleware-recursion-detection" "3.363.0" - "@aws-sdk/middleware-signing" "3.363.0" - "@aws-sdk/middleware-user-agent" "3.363.0" - "@aws-sdk/types" "3.357.0" - "@aws-sdk/util-endpoints" "3.357.0" - "@aws-sdk/util-user-agent-browser" "3.363.0" - "@aws-sdk/util-user-agent-node" "3.363.0" + "@aws-sdk/client-sts" "3.370.0" + "@aws-sdk/credential-provider-node" "3.370.0" + "@aws-sdk/middleware-host-header" "3.370.0" + "@aws-sdk/middleware-logger" "3.370.0" + "@aws-sdk/middleware-recursion-detection" "3.370.0" + "@aws-sdk/middleware-signing" "3.370.0" + "@aws-sdk/middleware-user-agent" "3.370.0" + "@aws-sdk/types" "3.370.0" + "@aws-sdk/util-endpoints" "3.370.0" + "@aws-sdk/util-user-agent-browser" "3.370.0" + "@aws-sdk/util-user-agent-node" "3.370.0" "@smithy/config-resolver" "^1.0.1" "@smithy/fetch-http-handler" "^1.0.1" "@smithy/hash-node" "^1.0.1" "@smithy/invalid-dependency" "^1.0.1" "@smithy/middleware-content-length" "^1.0.1" - "@smithy/middleware-endpoint" "^1.0.1" - "@smithy/middleware-retry" "^1.0.2" + "@smithy/middleware-endpoint" "^1.0.2" + "@smithy/middleware-retry" "^1.0.3" "@smithy/middleware-serde" "^1.0.1" "@smithy/middleware-stack" "^1.0.1" "@smithy/node-config-provider" "^1.0.1" "@smithy/node-http-handler" "^1.0.2" - "@smithy/protocol-http" "^1.0.1" + "@smithy/protocol-http" "^1.1.0" "@smithy/smithy-client" "^1.0.3" - "@smithy/types" "^1.0.0" + "@smithy/types" "^1.1.0" "@smithy/url-parser" "^1.0.1" "@smithy/util-base64" "^1.0.1" "@smithy/util-body-length-browser" "^1.0.1" "@smithy/util-body-length-node" "^1.0.1" "@smithy/util-defaults-mode-browser" "^1.0.1" "@smithy/util-defaults-mode-node" "^1.0.1" - "@smithy/util-retry" "^1.0.2" + "@smithy/util-retry" "^1.0.3" "@smithy/util-utf8" "^1.0.1" tslib "^2.5.0" -"@aws-sdk/client-sso-oidc@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.363.0.tgz#71240d729a0847fd5a7aaac09ed5a3a07c3666cf" - integrity sha512-V3Ebiq/zNtDS/O92HUWGBa7MY59RYSsqWd+E0XrXv6VYTA00RlMTbNcseivNgp2UghOgB9a20Nkz6EqAeIN+RQ== +"@aws-sdk/client-sso-oidc@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.370.0.tgz#db03c04cb6a23888dc60016eb67505a41ede410b" + integrity sha512-jAYOO74lmVXylQylqkPrjLzxvUnMKw476JCUTvCO6Q8nv3LzCWd76Ihgv/m9Q4M2Tbqi1iP2roVK5bstsXzEjA== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/middleware-host-header" "3.363.0" - "@aws-sdk/middleware-logger" "3.363.0" - "@aws-sdk/middleware-recursion-detection" "3.363.0" - "@aws-sdk/middleware-user-agent" "3.363.0" - "@aws-sdk/types" "3.357.0" - "@aws-sdk/util-endpoints" "3.357.0" - "@aws-sdk/util-user-agent-browser" "3.363.0" - "@aws-sdk/util-user-agent-node" "3.363.0" + "@aws-sdk/middleware-host-header" "3.370.0" + "@aws-sdk/middleware-logger" "3.370.0" + "@aws-sdk/middleware-recursion-detection" "3.370.0" + "@aws-sdk/middleware-user-agent" "3.370.0" + "@aws-sdk/types" "3.370.0" + "@aws-sdk/util-endpoints" "3.370.0" + "@aws-sdk/util-user-agent-browser" "3.370.0" + "@aws-sdk/util-user-agent-node" "3.370.0" "@smithy/config-resolver" "^1.0.1" "@smithy/fetch-http-handler" "^1.0.1" "@smithy/hash-node" "^1.0.1" "@smithy/invalid-dependency" "^1.0.1" "@smithy/middleware-content-length" "^1.0.1" - "@smithy/middleware-endpoint" "^1.0.1" - "@smithy/middleware-retry" "^1.0.2" + "@smithy/middleware-endpoint" "^1.0.2" + "@smithy/middleware-retry" "^1.0.3" "@smithy/middleware-serde" "^1.0.1" "@smithy/middleware-stack" "^1.0.1" "@smithy/node-config-provider" "^1.0.1" "@smithy/node-http-handler" "^1.0.2" - "@smithy/protocol-http" "^1.0.1" + "@smithy/protocol-http" "^1.1.0" "@smithy/smithy-client" "^1.0.3" - "@smithy/types" "^1.0.0" + "@smithy/types" "^1.1.0" "@smithy/url-parser" "^1.0.1" "@smithy/util-base64" "^1.0.1" "@smithy/util-body-length-browser" "^1.0.1" "@smithy/util-body-length-node" "^1.0.1" "@smithy/util-defaults-mode-browser" "^1.0.1" "@smithy/util-defaults-mode-node" "^1.0.1" - "@smithy/util-retry" "^1.0.2" + "@smithy/util-retry" "^1.0.3" "@smithy/util-utf8" "^1.0.1" tslib "^2.5.0" -"@aws-sdk/client-sso@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.363.0.tgz#b1939ee6769cf208f1dd4fbfa924c223da9d60ec" - integrity sha512-PZ+HfKSgS4hlMnJzG+Ev8/mgHd/b/ETlJWPSWjC/f2NwVoBQkBnqHjdyEx7QjF6nksJozcVh5Q+kkYLKc/QwBQ== +"@aws-sdk/client-sso@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.370.0.tgz#68aea97ecb2e5e6c817dfd3a1dd9fa4e09ff6e1c" + integrity sha512-0Ty1iHuzNxMQtN7nahgkZr4Wcu1XvqGfrQniiGdKKif9jG/4elxsQPiydRuQpFqN6b+bg7wPP7crFP1uTxx2KQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/middleware-host-header" "3.363.0" - "@aws-sdk/middleware-logger" "3.363.0" - "@aws-sdk/middleware-recursion-detection" "3.363.0" - "@aws-sdk/middleware-user-agent" "3.363.0" - "@aws-sdk/types" "3.357.0" - "@aws-sdk/util-endpoints" "3.357.0" - "@aws-sdk/util-user-agent-browser" "3.363.0" - "@aws-sdk/util-user-agent-node" "3.363.0" + "@aws-sdk/middleware-host-header" "3.370.0" + "@aws-sdk/middleware-logger" "3.370.0" + "@aws-sdk/middleware-recursion-detection" "3.370.0" + "@aws-sdk/middleware-user-agent" "3.370.0" + "@aws-sdk/types" "3.370.0" + "@aws-sdk/util-endpoints" "3.370.0" + "@aws-sdk/util-user-agent-browser" "3.370.0" + "@aws-sdk/util-user-agent-node" "3.370.0" "@smithy/config-resolver" "^1.0.1" "@smithy/fetch-http-handler" "^1.0.1" "@smithy/hash-node" "^1.0.1" "@smithy/invalid-dependency" "^1.0.1" "@smithy/middleware-content-length" "^1.0.1" - "@smithy/middleware-endpoint" "^1.0.1" - "@smithy/middleware-retry" "^1.0.2" + "@smithy/middleware-endpoint" "^1.0.2" + "@smithy/middleware-retry" "^1.0.3" "@smithy/middleware-serde" "^1.0.1" "@smithy/middleware-stack" "^1.0.1" "@smithy/node-config-provider" "^1.0.1" "@smithy/node-http-handler" "^1.0.2" - "@smithy/protocol-http" "^1.0.1" + "@smithy/protocol-http" "^1.1.0" "@smithy/smithy-client" "^1.0.3" - "@smithy/types" "^1.0.0" + "@smithy/types" "^1.1.0" "@smithy/url-parser" "^1.0.1" "@smithy/util-base64" "^1.0.1" "@smithy/util-body-length-browser" "^1.0.1" "@smithy/util-body-length-node" "^1.0.1" "@smithy/util-defaults-mode-browser" "^1.0.1" "@smithy/util-defaults-mode-node" "^1.0.1" - "@smithy/util-retry" "^1.0.2" + "@smithy/util-retry" "^1.0.3" "@smithy/util-utf8" "^1.0.1" tslib "^2.5.0" -"@aws-sdk/client-sts@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.363.0.tgz#c02b3cf3bd2ef9d54195323370db964cd1df4711" - integrity sha512-0jj14WvBPJQ8xr72cL0mhlmQ90tF0O0wqXwSbtog6PsC8+KDE6Yf+WsxsumyI8E5O8u3eYijBL+KdqG07F/y/w== +"@aws-sdk/client-sts@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.370.0.tgz#65879fa35b396035dcab446c782056ef768f48af" + integrity sha512-utFxOPWIzbN+3kc415Je2o4J72hOLNhgR2Gt5EnRSggC3yOnkC4GzauxG8n7n5gZGBX45eyubHyPOXLOIyoqQA== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/credential-provider-node" "3.363.0" - "@aws-sdk/middleware-host-header" "3.363.0" - "@aws-sdk/middleware-logger" "3.363.0" - "@aws-sdk/middleware-recursion-detection" "3.363.0" - "@aws-sdk/middleware-sdk-sts" "3.363.0" - "@aws-sdk/middleware-signing" "3.363.0" - "@aws-sdk/middleware-user-agent" "3.363.0" - "@aws-sdk/types" "3.357.0" - "@aws-sdk/util-endpoints" "3.357.0" - "@aws-sdk/util-user-agent-browser" "3.363.0" - "@aws-sdk/util-user-agent-node" "3.363.0" + "@aws-sdk/credential-provider-node" "3.370.0" + "@aws-sdk/middleware-host-header" "3.370.0" + "@aws-sdk/middleware-logger" "3.370.0" + "@aws-sdk/middleware-recursion-detection" "3.370.0" + "@aws-sdk/middleware-sdk-sts" "3.370.0" + "@aws-sdk/middleware-signing" "3.370.0" + "@aws-sdk/middleware-user-agent" "3.370.0" + "@aws-sdk/types" "3.370.0" + "@aws-sdk/util-endpoints" "3.370.0" + "@aws-sdk/util-user-agent-browser" "3.370.0" + "@aws-sdk/util-user-agent-node" "3.370.0" "@smithy/config-resolver" "^1.0.1" "@smithy/fetch-http-handler" "^1.0.1" "@smithy/hash-node" "^1.0.1" "@smithy/invalid-dependency" "^1.0.1" "@smithy/middleware-content-length" "^1.0.1" - "@smithy/middleware-endpoint" "^1.0.1" - "@smithy/middleware-retry" "^1.0.1" + "@smithy/middleware-endpoint" "^1.0.2" + "@smithy/middleware-retry" "^1.0.3" "@smithy/middleware-serde" "^1.0.1" "@smithy/middleware-stack" "^1.0.1" "@smithy/node-config-provider" "^1.0.1" - "@smithy/node-http-handler" "^1.0.1" + "@smithy/node-http-handler" "^1.0.2" "@smithy/protocol-http" "^1.1.0" - "@smithy/smithy-client" "^1.0.2" + "@smithy/smithy-client" "^1.0.3" "@smithy/types" "^1.1.0" "@smithy/url-parser" "^1.0.1" "@smithy/util-base64" "^1.0.1" @@ -302,165 +260,133 @@ "@smithy/util-body-length-node" "^1.0.1" "@smithy/util-defaults-mode-browser" "^1.0.1" "@smithy/util-defaults-mode-node" "^1.0.1" - "@smithy/util-retry" "^1.0.1" + "@smithy/util-retry" "^1.0.3" "@smithy/util-utf8" "^1.0.1" fast-xml-parser "4.2.5" tslib "^2.5.0" -"@aws-sdk/credential-provider-cognito-identity@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.363.0.tgz#0f4ae7cd282b61a5dfdd7d38a02495411c926dc9" - integrity sha512-5x42JvqEsBUrm6/qdf0WWe4mlmJjPItxamQhRjuOzeQD/BxsA2W5VS/7n0Ws0e27DNhlnUErcIJd+bBy6j1fqA== +"@aws-sdk/credential-provider-env@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.370.0.tgz#edd507a88b36b967da048255f4a478ad92d1c5aa" + integrity sha512-raR3yP/4GGbKFRPP5hUBNkEmTnzxI9mEc2vJAJrcv4G4J4i/UP6ELiLInQ5eO2/VcV/CeKGZA3t7d1tsJ+jhCg== dependencies: - "@aws-sdk/client-cognito-identity" "3.363.0" - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/property-provider" "^1.0.1" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-env@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.363.0.tgz#5b8471a243cdb54696ecae99ad4cc1c48d687657" - integrity sha512-VAQ3zITT2Q0acht0HezouYnMFKZ2vIOa20X4zQA3WI0HfaP4D6ga6KaenbDcb/4VFiqfqiRHfdyXHP0ThcDRMA== +"@aws-sdk/credential-provider-ini@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.370.0.tgz#4e569b8054b4fba2f0a0a7fa88af84b1f8d78c0b" + integrity sha512-eJyapFKa4NrC9RfTgxlXnXfS9InG/QMEUPPVL+VhG7YS6nKqetC1digOYgivnEeu+XSKE0DJ7uZuXujN2Y7VAQ== dependencies: - "@aws-sdk/types" "3.357.0" - "@smithy/property-provider" "^1.0.1" - "@smithy/types" "^1.1.0" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-ini@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.363.0.tgz#e77e65e1ffc7c736aa724ebdf038e99dca57a87b" - integrity sha512-ZYN+INoqyX5FVC3rqUxB6O8nOWkr0gHRRBm1suoOlmuFJ/WSlW/uUGthRBY5x1AQQnBF8cpdlxZzGHd41lFVNw== - dependencies: - "@aws-sdk/credential-provider-env" "3.363.0" - "@aws-sdk/credential-provider-process" "3.363.0" - "@aws-sdk/credential-provider-sso" "3.363.0" - "@aws-sdk/credential-provider-web-identity" "3.363.0" - "@aws-sdk/types" "3.357.0" + "@aws-sdk/credential-provider-env" "3.370.0" + "@aws-sdk/credential-provider-process" "3.370.0" + "@aws-sdk/credential-provider-sso" "3.370.0" + "@aws-sdk/credential-provider-web-identity" "3.370.0" + "@aws-sdk/types" "3.370.0" "@smithy/credential-provider-imds" "^1.0.1" "@smithy/property-provider" "^1.0.1" "@smithy/shared-ini-file-loader" "^1.0.1" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-node@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.363.0.tgz#70815b3c8bc98d9afd148b851c8fdae9ce11fcd6" - integrity sha512-C1qXFIN2yMxD6pGgug0vR1UhScOki6VqdzuBHzXZAGu7MOjvgHNdscEcb3CpWnITHaPL2ztkiw75T1sZ7oIgQg== - dependencies: - "@aws-sdk/credential-provider-env" "3.363.0" - "@aws-sdk/credential-provider-ini" "3.363.0" - "@aws-sdk/credential-provider-process" "3.363.0" - "@aws-sdk/credential-provider-sso" "3.363.0" - "@aws-sdk/credential-provider-web-identity" "3.363.0" - "@aws-sdk/types" "3.357.0" +"@aws-sdk/credential-provider-node@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.370.0.tgz#74605644ccbd9e8237223318a7955f4ab2ff0d86" + integrity sha512-gkFiotBFKE4Fcn8CzQnMeab9TAR06FEAD02T4ZRYW1xGrBJOowmje9dKqdwQFHSPgnWAP+8HoTA8iwbhTLvjNA== + dependencies: + "@aws-sdk/credential-provider-env" "3.370.0" + "@aws-sdk/credential-provider-ini" "3.370.0" + "@aws-sdk/credential-provider-process" "3.370.0" + "@aws-sdk/credential-provider-sso" "3.370.0" + "@aws-sdk/credential-provider-web-identity" "3.370.0" + "@aws-sdk/types" "3.370.0" "@smithy/credential-provider-imds" "^1.0.1" "@smithy/property-provider" "^1.0.1" "@smithy/shared-ini-file-loader" "^1.0.1" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-process@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.363.0.tgz#08608f6da246084f9b20481ac0de17f04ae54b4d" - integrity sha512-fOKAINU7Rtj2T8pP13GdCt+u0Ml3gYynp8ki+1jMZIQ+Ju/MdDOqZpKMFKicMn3Z1ttUOgqr+grUdus6z8ceBQ== +"@aws-sdk/credential-provider-process@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.370.0.tgz#f7b94d2ccfda3b067cb23ea832b10c692c831855" + integrity sha512-0BKFFZmUO779Xdw3u7wWnoWhYA4zygxJbgGVSyjkOGBvdkbPSTTcdwT1KFkaQy2kOXYeZPl+usVVRXs+ph4ejg== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/property-provider" "^1.0.1" "@smithy/shared-ini-file-loader" "^1.0.1" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-sso@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.363.0.tgz#949190c9ea510d9772aef9c61345575f4b40b44d" - integrity sha512-5RUZ5oM0lwZSo3EehT0dXggOjgtxFogpT3cZvoLGtIwrPBvm8jOQPXQUlaqCj10ThF1sYltEyukz/ovtDwYGew== +"@aws-sdk/credential-provider-sso@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.370.0.tgz#4c57f93d73f198d7e1e53fbfcdf72c053bc9c682" + integrity sha512-PFroYm5hcPSfC/jkZnCI34QFL3I7WVKveVk6/F3fud/cnP8hp6YjA9NiTNbqdFSzsyoiN/+e5fZgNKih8vVPTA== dependencies: - "@aws-sdk/client-sso" "3.363.0" - "@aws-sdk/token-providers" "3.363.0" - "@aws-sdk/types" "3.357.0" + "@aws-sdk/client-sso" "3.370.0" + "@aws-sdk/token-providers" "3.370.0" + "@aws-sdk/types" "3.370.0" "@smithy/property-provider" "^1.0.1" "@smithy/shared-ini-file-loader" "^1.0.1" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-web-identity@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.363.0.tgz#a5312519126ff7c3fea56ffefa0e51ef9383663c" - integrity sha512-Z6w7fjgy79pAax580wdixbStQw10xfyZ+hOYLcPudoYFKjoNx0NQBejg5SwBzCF/HQL23Ksm9kDfbXDX9fkPhA== +"@aws-sdk/credential-provider-web-identity@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.370.0.tgz#c5831bb656bea1fe3b300e495e19a33bc90f4d84" + integrity sha512-CFaBMLRudwhjv1sDzybNV93IaT85IwS+L8Wq6VRMa0mro1q9rrWsIZO811eF+k0NEPfgU1dLH+8Vc2qhw4SARQ== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/property-provider" "^1.0.1" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/credential-providers@^3.186.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-providers/-/credential-providers-3.363.0.tgz#592700058349ca6fcc3f23dfcec14c9d6c0c929a" - integrity sha512-hVa1DdYasnLud2EKjDAlDHiV/+H/Zq52chHU00c/R8XwPu1s0kZX3NMmlt0D2HhYqC1mUwtdmE58Jra2POviQQ== - dependencies: - "@aws-sdk/client-cognito-identity" "3.363.0" - "@aws-sdk/client-sso" "3.363.0" - "@aws-sdk/client-sts" "3.363.0" - "@aws-sdk/credential-provider-cognito-identity" "3.363.0" - "@aws-sdk/credential-provider-env" "3.363.0" - "@aws-sdk/credential-provider-ini" "3.363.0" - "@aws-sdk/credential-provider-node" "3.363.0" - "@aws-sdk/credential-provider-process" "3.363.0" - "@aws-sdk/credential-provider-sso" "3.363.0" - "@aws-sdk/credential-provider-web-identity" "3.363.0" - "@aws-sdk/types" "3.357.0" - "@smithy/credential-provider-imds" "^1.0.1" - "@smithy/property-provider" "^1.0.1" - "@smithy/types" "^1.1.0" - tslib "^2.5.0" - -"@aws-sdk/middleware-host-header@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.363.0.tgz#3fc25569c1fdbb29ee7b95690d222743b9791210" - integrity sha512-FobpclDCf5Y1ueyJDmb9MqguAdPssNMlnqWQpujhYVABq69KHu73fSCWSauFPUrw7YOpV8kG1uagDF0POSxHzA== +"@aws-sdk/middleware-host-header@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.370.0.tgz#645472416efd16b22a66b0aa1d52f48cf5699feb" + integrity sha512-CPXOm/TnOFC7KyXcJglICC7OiA7Kj6mT3ChvEijr56TFOueNHvJdV4aNIFEQy0vGHOWtY12qOWLNto/wYR1BAQ== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/protocol-http" "^1.1.0" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/middleware-logger@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.363.0.tgz#64ebef9910802f9437cae8900e8825ca5141c9ed" - integrity sha512-SSGgthScYnFGTOw8EzbkvquqweFmvn7uJihkpFekbtBNGC/jGOGO+8ziHjTQ8t/iI/YKubEwv+LMi0f77HKSEg== +"@aws-sdk/middleware-logger@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.370.0.tgz#c9f694d7e1dd47b5e6e8eab94793fc1e272b1e26" + integrity sha512-cQMq9SaZ/ORmTJPCT6VzMML7OxFdQzNkhMAgKpTDl+tdPWynlHF29E5xGoSzROnThHlQPCjogU0NZ8AxI0SWPA== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/middleware-recursion-detection@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.363.0.tgz#bd8b8010f5be5d7e90a97bf9e55a7980289b1600" - integrity sha512-MWD/57QgI/N7fG8rtzDTUdSqNpYohQfgj9XCFAoVeI/bU4usrkOrew43L4smJG4XrDxlNT8lSJlDtd64tuiUZA== +"@aws-sdk/middleware-recursion-detection@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.370.0.tgz#e5e8fd1d2ff1ade91135295dabcaa81c311ce00b" + integrity sha512-L7ZF/w0lAAY/GK1khT8VdoU0XB7nWHk51rl/ecAg64J70dHnMOAg8n+5FZ9fBu/xH1FwUlHOkwlodJOgzLJjtg== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/protocol-http" "^1.1.0" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/middleware-sdk-sts@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.363.0.tgz#41b10aa8b8004bda9156cadde3b2302a84309e6a" - integrity sha512-1yy2Ac50FO8BrODaw5bPWvVrRhaVLqXTFH6iHB+dJLPUkwtY5zLM3Mp+9Ilm7kME+r7oIB1wuO6ZB1Lf4ZszIw== +"@aws-sdk/middleware-sdk-sts@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.370.0.tgz#0599a624fe5cabe75cd7d9e7420927b102356fa2" + integrity sha512-ykbsoVy0AJtVbuhAlTAMcaz/tCE3pT8nAp0L7CQQxSoanRCvOux7au0KwMIQVhxgnYid4dWVF6d00SkqU5MXRA== dependencies: - "@aws-sdk/middleware-signing" "3.363.0" - "@aws-sdk/types" "3.357.0" + "@aws-sdk/middleware-signing" "3.370.0" + "@aws-sdk/types" "3.370.0" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/middleware-signing@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.363.0.tgz#81067698e0566584f0ca30be56232758f69e2232" - integrity sha512-/7qia715pt9JKYIPDGu22WmdZxD8cfF/5xB+1kmILg7ZtjO0pPuTaCNJ7xiIuFd7Dn7JXp5lop08anX/GOhNRQ== +"@aws-sdk/middleware-signing@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.370.0.tgz#c094026251faa17a24f61630d56152f7b073e6cf" + integrity sha512-Dwr/RTCWOXdm394wCwICGT2VNOTMRe4IGPsBRJAsM24pm+EEqQzSS3Xu/U/zF4exuxqpMta4wec4QpSarPNTxA== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/property-provider" "^1.0.1" "@smithy/protocol-http" "^1.1.0" "@smithy/signature-v4" "^1.0.1" @@ -468,42 +394,43 @@ "@smithy/util-middleware" "^1.0.1" tslib "^2.5.0" -"@aws-sdk/middleware-user-agent@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.363.0.tgz#a75a7ca5c791a68d750736c87b968b54d394443d" - integrity sha512-ri8YaQvXP6odteVTMfxPqFR26Q0h9ejtqhUDv47P34FaKXedEM4nC6ix6o+5FEYj6l8syGyktftZ5O70NoEhug== +"@aws-sdk/middleware-user-agent@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.370.0.tgz#a2bf71baf6407654811a02e4d276a2eec3996fdb" + integrity sha512-2+3SB6MtMAq1+gVXhw0Y3ONXuljorh6ijnxgTpv+uQnBW5jHCUiAS8WDYiDEm7i9euJPbvJfM8WUrSMDMU6Cog== dependencies: - "@aws-sdk/types" "3.357.0" - "@aws-sdk/util-endpoints" "3.357.0" + "@aws-sdk/types" "3.370.0" + "@aws-sdk/util-endpoints" "3.370.0" "@smithy/protocol-http" "^1.1.0" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/token-providers@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.363.0.tgz#c211ed6db62620c46194506db6d785f5c36aedc5" - integrity sha512-6+0aJ1zugNgsMmhTtW2LBWxOVSaXCUk2q3xyTchSXkNzallYaRiZMRkieW+pKNntnu0g5H1T0zyfCO0tbXwxEA== +"@aws-sdk/token-providers@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.370.0.tgz#e5229f2d116887c90ec103e024583be05c1f506c" + integrity sha512-EyR2ZYr+lJeRiZU2/eLR+mlYU9RXLQvNyGFSAekJKgN13Rpq/h0syzXVFLP/RSod/oZenh/fhVZ2HwlZxuGBtQ== dependencies: - "@aws-sdk/client-sso-oidc" "3.363.0" - "@aws-sdk/types" "3.357.0" + "@aws-sdk/client-sso-oidc" "3.370.0" + "@aws-sdk/types" "3.370.0" "@smithy/property-provider" "^1.0.1" "@smithy/shared-ini-file-loader" "^1.0.1" "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/types@3.357.0", "@aws-sdk/types@^3.222.0": - version "3.357.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.357.0.tgz#8491da71a4291cc2661c26a75089e86532b6a3b5" - integrity sha512-/riCRaXg3p71BeWnShrai0y0QTdXcouPSM0Cn1olZbzTf7s71aLEewrc96qFrL70XhY4XvnxMpqQh+r43XIL3g== +"@aws-sdk/types@3.370.0", "@aws-sdk/types@^3.222.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.370.0.tgz#79e0e4927529c957b5c5c2a00f7590a76784a5e4" + integrity sha512-8PGMKklSkRKjunFhzM2y5Jm0H2TBu7YRNISdYzXLUHKSP9zlMEYagseKVdmox0zKHf1LXVNuSlUV2b6SRrieCQ== dependencies: + "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@aws-sdk/util-endpoints@3.357.0": - version "3.357.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.357.0.tgz#eaa7b4481bbd9fc8f13412b308ba4129d8fa2004" - integrity sha512-XHKyS5JClT9su9hDif715jpZiWHQF9gKZXER8tW0gOizU3R9cyWc9EsJ2BRhFNhi7nt/JF/CLUEc5qDx3ETbUw== +"@aws-sdk/util-endpoints@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.370.0.tgz#bf1f4653c3afc89d4e79aa4895dd3dffbb56c930" + integrity sha512-5ltVAnM79nRlywwzZN5i8Jp4tk245OCGkKwwXbnDU+gq7zT3CIOsct1wNZvmpfZEPGt/bv7/NyRcjP+7XNsX/g== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" tslib "^2.5.0" "@aws-sdk/util-locate-window@^3.0.0": @@ -513,22 +440,22 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/util-user-agent-browser@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.363.0.tgz#6f0655976f4f5889d6f0abed6c6cdc665cab524f" - integrity sha512-fk9ymBUIYbxiGm99Cn+kAAXmvMCWTf/cHAcB79oCXV4ELXdPa9lN5xQhZRFNxLUeXG4OAMEuCAUUuZEj8Fnc1Q== +"@aws-sdk/util-user-agent-browser@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.370.0.tgz#df144f5f1a65578842b79d49555c754a531d85f0" + integrity sha512-028LxYZMQ0DANKhW+AKFQslkScZUeYlPmSphrCIXgdIItRZh6ZJHGzE7J/jDsEntZOrZJsjI4z0zZ5W2idj04w== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/types" "^1.1.0" bowser "^2.11.0" tslib "^2.5.0" -"@aws-sdk/util-user-agent-node@3.363.0": - version "3.363.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.363.0.tgz#9df26188a3d22694b4d06f5f40c489cb22fddb48" - integrity sha512-Fli/dvgGA9hdnQUrYb1//wNSFlK2jAfdJcfNXA6SeBYzSeH5pVGYF4kXF0FCdnMA3Fef+Zn1zAP/hw9v8VJHWQ== +"@aws-sdk/util-user-agent-node@3.370.0": + version "3.370.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.370.0.tgz#96d8420b42cbebd498de8b94886340d11c97a34b" + integrity sha512-33vxZUp8vxTT/DGYIR3PivQm07sSRGWI+4fCv63Rt7Q++fO24E0kQtmVAlikRY810I10poD6rwILVtITtFSzkg== dependencies: - "@aws-sdk/types" "3.357.0" + "@aws-sdk/types" "3.370.0" "@smithy/node-config-provider" "^1.0.1" "@smithy/types" "^1.1.0" tslib "^2.5.0" @@ -540,49 +467,49 @@ dependencies: tslib "^2.3.1" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.5": +"@babel/code-frame@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== dependencies: "@babel/highlight" "^7.22.5" -"@babel/compat-data@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.6.tgz#15606a20341de59ba02cd2fcc5086fcbe73bf544" - integrity sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg== +"@babel/compat-data@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" + integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.17.10": - version "7.22.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.8.tgz#386470abe884302db9c82e8e5e87be9e46c86785" - integrity sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw== +"@babel/core@^7.22.9", "@babel/core@^7.7.5": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.9.tgz#bd96492c68822198f33e8a256061da3cf391f58f" + integrity sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-module-transforms" "^7.22.5" + "@babel/generator" "^7.22.9" + "@babel/helper-compilation-targets" "^7.22.9" + "@babel/helper-module-transforms" "^7.22.9" "@babel/helpers" "^7.22.6" "@babel/parser" "^7.22.7" "@babel/template" "^7.22.5" "@babel/traverse" "^7.22.8" "@babel/types" "^7.22.5" - "@nicolo-ribaudo/semver-v6" "^6.3.3" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.2" + semver "^6.3.1" -"@babel/eslint-parser@^7.17.0": - version "7.22.7" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.7.tgz#d2807fbd1fa4376162716da63dfd3c69a2249fed" - integrity sha512-LH6HJqjOyu/Qtp7LuSycZXK/CYXQ4ohdkliEaL1QTdtOXVdOVpTBKVxAo/+eeyt+x/2SRzB+zUPduVl+xiEvdg== +"@babel/eslint-parser@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.9.tgz#75f8aa978d1e76c87cc6f26c1ea16ae58804d390" + integrity sha512-xdMkt39/nviO/4vpVdrEYPwXCsYIXSSAr6mC7WQsNIlGnuxKyKE7GZjalcnbSWiC4OXGNNN3UQPeHfjSC6sTDA== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" - "@nicolo-ribaudo/semver-v6" "^6.3.3" eslint-visitor-keys "^2.1.0" + semver "^6.3.1" -"@babel/generator@^7.22.7", "@babel/generator@^7.7.2": +"@babel/generator@^7.22.7": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.7.tgz#a6b8152d5a621893f2c9dacf9a4e286d520633d5" integrity sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ== @@ -592,16 +519,26 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz#e30d61abe9480aa5a83232eb31c111be922d2e52" - integrity sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA== +"@babel/generator@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d" + integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw== + dependencies: + "@babel/types" "^7.22.5" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz#f9d0a7aaaa7cd32a3f31c9316a69f5a9bcacb892" + integrity sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw== dependencies: - "@babel/compat-data" "^7.22.6" + "@babel/compat-data" "^7.22.9" "@babel/helper-validator-option" "^7.22.5" - "@nicolo-ribaudo/semver-v6" "^6.3.3" browserslist "^4.21.9" lru-cache "^5.1.1" + semver "^6.3.1" "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" @@ -630,21 +567,18 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-module-transforms@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef" - integrity sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw== +"@babel/helper-module-transforms@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz#92dfcb1fbbb2bc62529024f72d942a8c97142129" + integrity sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ== dependencies: "@babel/helper-environment-visitor" "^7.22.5" "@babel/helper-module-imports" "^7.22.5" "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.5" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": +"@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== @@ -663,7 +597,7 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-split-export-declaration@^7.22.5", "@babel/helper-split-export-declaration@^7.22.6": +"@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== @@ -703,7 +637,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.5", "@babel/parser@^7.22.7": +"@babel/parser@^7.22.5", "@babel/parser@^7.22.7": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== @@ -717,76 +651,6 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" @@ -794,21 +658,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.7.2": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz#aac8d383b062c5072c647a31ef990c1d0af90272" - integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/template@^7.22.5", "@babel/template@^7.3.3": +"@babel/template@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== @@ -817,7 +667,7 @@ "@babel/parser" "^7.22.5" "@babel/types" "^7.22.5" -"@babel/traverse@^7.22.5", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8", "@babel/traverse@^7.7.2": +"@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": version "7.22.8" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== @@ -833,7 +683,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.3.3": +"@babel/types@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== @@ -842,11 +692,6 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -919,199 +764,6 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.3.tgz#2030606ec03a18c31803b8a36382762e447655df" - integrity sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw== - dependencies: - "@jest/types" "^28.1.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^28.1.3" - jest-util "^28.1.3" - slash "^3.0.0" - -"@jest/core@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.1.3.tgz#0ebf2bd39840f1233cd5f2d1e6fc8b71bd5a1ac7" - integrity sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA== - dependencies: - "@jest/console" "^28.1.3" - "@jest/reporters" "^28.1.3" - "@jest/test-result" "^28.1.3" - "@jest/transform" "^28.1.3" - "@jest/types" "^28.1.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^28.1.3" - jest-config "^28.1.3" - jest-haste-map "^28.1.3" - jest-message-util "^28.1.3" - jest-regex-util "^28.0.2" - jest-resolve "^28.1.3" - jest-resolve-dependencies "^28.1.3" - jest-runner "^28.1.3" - jest-runtime "^28.1.3" - jest-snapshot "^28.1.3" - jest-util "^28.1.3" - jest-validate "^28.1.3" - jest-watcher "^28.1.3" - micromatch "^4.0.4" - pretty-format "^28.1.3" - rimraf "^3.0.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.3.tgz#abed43a6b040a4c24fdcb69eab1f97589b2d663e" - integrity sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA== - dependencies: - "@jest/fake-timers" "^28.1.3" - "@jest/types" "^28.1.3" - "@types/node" "*" - jest-mock "^28.1.3" - -"@jest/expect-utils@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525" - integrity sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA== - dependencies: - jest-get-type "^28.0.2" - -"@jest/expect@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.3.tgz#9ac57e1d4491baca550f6bdbd232487177ad6a72" - integrity sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw== - dependencies: - expect "^28.1.3" - jest-snapshot "^28.1.3" - -"@jest/fake-timers@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.1.3.tgz#230255b3ad0a3d4978f1d06f70685baea91c640e" - integrity sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw== - dependencies: - "@jest/types" "^28.1.3" - "@sinonjs/fake-timers" "^9.1.2" - "@types/node" "*" - jest-message-util "^28.1.3" - jest-mock "^28.1.3" - jest-util "^28.1.3" - -"@jest/globals@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.3.tgz#a601d78ddc5fdef542728309894895b4a42dc333" - integrity sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA== - dependencies: - "@jest/environment" "^28.1.3" - "@jest/expect" "^28.1.3" - "@jest/types" "^28.1.3" - -"@jest/reporters@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.1.3.tgz#9adf6d265edafc5fc4a434cfb31e2df5a67a369a" - integrity sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^28.1.3" - "@jest/test-result" "^28.1.3" - "@jest/transform" "^28.1.3" - "@jest/types" "^28.1.3" - "@jridgewell/trace-mapping" "^0.3.13" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^28.1.3" - jest-util "^28.1.3" - jest-worker "^28.1.3" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - terminal-link "^2.0.0" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.1.3.tgz#ad8b86a66f11f33619e3d7e1dcddd7f2d40ff905" - integrity sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg== - dependencies: - "@sinclair/typebox" "^0.24.1" - -"@jest/source-map@^28.1.2": - version "28.1.2" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-28.1.2.tgz#7fe832b172b497d6663cdff6c13b0a920e139e24" - integrity sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww== - dependencies: - "@jridgewell/trace-mapping" "^0.3.13" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.3.tgz#5eae945fd9f4b8fcfce74d239e6f725b6bf076c5" - integrity sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg== - dependencies: - "@jest/console" "^28.1.3" - "@jest/types" "^28.1.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz#9d0c283d906ac599c74bde464bc0d7e6a82886c3" - integrity sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw== - dependencies: - "@jest/test-result" "^28.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^28.1.3" - slash "^3.0.0" - -"@jest/transform@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.3.tgz#59d8098e50ab07950e0f2fc0fc7ec462371281b0" - integrity sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^28.1.3" - "@jridgewell/trace-mapping" "^0.3.13" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^1.4.0" - fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^28.1.3" - jest-regex-util "^28.0.2" - jest-util "^28.1.3" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.1" - -"@jest/types@^28.1.3": - version "28.1.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.3.tgz#b05de80996ff12512bc5ceb1d208285a7d11748b" - integrity sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ== - dependencies: - "@jest/schemas" "^28.1.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" @@ -1141,7 +793,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.18" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== @@ -1155,9 +807,9 @@ integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== "@mapbox/node-pre-gyp@^1.0.10": - version "1.0.10" - resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c" - integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA== + version "1.0.11" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" + integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== dependencies: detect-libc "^2.0.0" https-proxy-agent "^5.0.0" @@ -1206,11 +858,6 @@ dependencies: eslint-scope "5.1.1" -"@nicolo-ribaudo/semver-v6@^6.3.3": - version "6.3.3" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz#ea6d23ade78a325f7a52750aab1526b02b628c29" - integrity sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1232,24 +879,17 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@sinclair/typebox@^0.24.1": - version "0.24.51" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" - integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== - -"@sinonjs/commons@^1.7.0": - version "1.8.6" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" - integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^9.1.2": - version "9.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" - integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== +"@pkgr/utils@^2.3.1": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" + integrity sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw== dependencies: - "@sinonjs/commons" "^1.7.0" + cross-spawn "^7.0.3" + fast-glob "^3.3.0" + is-glob "^4.0.3" + open "^9.1.0" + picocolors "^1.0.0" + tslib "^2.6.0" "@smithy/abort-controller@^1.0.2": version "1.0.2" @@ -1335,7 +975,7 @@ "@smithy/types" "^1.1.1" tslib "^2.5.0" -"@smithy/middleware-endpoint@^1.0.1": +"@smithy/middleware-endpoint@^1.0.2": version "1.0.3" resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-1.0.3.tgz#ff4b1c0a83eb8d8b8d3937f434a95efbbf43e1cd" integrity sha512-GsWvTXMFjSgl617PCE2km//kIjjtvMRrR2GAuRDIS9sHiLwmkS46VWaVYy+XE7ubEsEtzZ5yK2e8TKDR6Qr5Lw== @@ -1346,7 +986,7 @@ "@smithy/util-middleware" "^1.0.2" tslib "^2.5.0" -"@smithy/middleware-retry@^1.0.1", "@smithy/middleware-retry@^1.0.2": +"@smithy/middleware-retry@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-1.0.4.tgz#8e9de0713dac7f7af405477d46bd4525ca7b9ea8" integrity sha512-G7uRXGFL8c3F7APnoIMTtNAHH8vT4F2qVnAWGAZaervjupaUQuRRHYBLYubK0dWzOZz86BtAXKieJ5p+Ni2Xpg== @@ -1384,7 +1024,7 @@ "@smithy/types" "^1.1.1" tslib "^2.5.0" -"@smithy/node-http-handler@^1.0.1", "@smithy/node-http-handler@^1.0.2", "@smithy/node-http-handler@^1.0.3": +"@smithy/node-http-handler@^1.0.2", "@smithy/node-http-handler@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-1.0.3.tgz#89b556ca2bdcce7a994a9da1ea265094d76d4791" integrity sha512-PcPUSzTbIb60VCJCiH0PU0E6bwIekttsIEf5Aoo/M0oTfiqsxHTn0Rcij6QoH6qJy6piGKXzLSegspXg5+Kq6g== @@ -1403,7 +1043,7 @@ "@smithy/types" "^1.1.1" tslib "^2.5.0" -"@smithy/protocol-http@^1.0.1", "@smithy/protocol-http@^1.1.0", "@smithy/protocol-http@^1.1.1": +"@smithy/protocol-http@^1.1.0", "@smithy/protocol-http@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-1.1.1.tgz#10977cf71631eed4f5ad1845408920238d52cdba" integrity sha512-mFLFa2sSvlUxm55U7B4YCIsJJIMkA6lHxwwqOaBkral1qxFz97rGffP/mmd4JDuin1EnygiO5eNJGgudiUgmDQ== @@ -1455,7 +1095,7 @@ "@smithy/util-utf8" "^1.0.2" tslib "^2.5.0" -"@smithy/smithy-client@^1.0.2", "@smithy/smithy-client@^1.0.3": +"@smithy/smithy-client@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-1.0.4.tgz#96d03d123d117a637c679a79bb8eae96e3857bd9" integrity sha512-gpo0Xl5Nyp9sgymEfpt7oa9P2q/GlM3VmQIdm+FeH0QEdYOQx3OtvwVmBYAMv2FIPWxkMZlsPYRTnEiBTK5TYg== @@ -1465,7 +1105,7 @@ "@smithy/util-stream" "^1.0.2" tslib "^2.5.0" -"@smithy/types@^1.0.0", "@smithy/types@^1.1.0", "@smithy/types@^1.1.1": +"@smithy/types@^1.1.0", "@smithy/types@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@smithy/types/-/types-1.1.1.tgz#949394a22e13e7077471bae0d18c146e5f62c456" integrity sha512-tMpkreknl2gRrniHeBtdgQwaOlo39df8RxSrwsHVNIGXULy5XP6KqgScUw2m12D15wnJCKWxVhCX+wbrBW/y7g== @@ -1554,7 +1194,7 @@ dependencies: tslib "^2.5.0" -"@smithy/util-retry@^1.0.1", "@smithy/util-retry@^1.0.2", "@smithy/util-retry@^1.0.4": +"@smithy/util-retry@^1.0.3", "@smithy/util-retry@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-1.0.4.tgz#9d95df3884981414163d5f780d38e3529384d9ad" integrity sha512-RnZPVFvRoqdj2EbroDo3OsnnQU8eQ4AlnZTOGusbYKybH3269CFdrZfZJloe60AQjX7di3J6t/79PjwCLO5Khw== @@ -1596,39 +1236,6 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== -"@types/babel__core@^7.1.14": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.1.tgz#916ecea274b0c776fec721e333e55762d3a9614b" - integrity sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.4" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" - integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.1" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" - integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.1.tgz#dd6f1d2411ae677dcb2db008c962598be31d6acf" - integrity sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg== - dependencies: - "@babel/types" "^7.20.7" - "@types/cookie@^0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" @@ -1641,57 +1248,21 @@ dependencies: "@types/node" "*" -"@types/graceful-fs@^4.1.3": - version "4.1.6" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae" - integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== - -"@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== - dependencies: - "@types/istanbul-lib-report" "*" - "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": version "7.0.12" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== "@types/node@*", "@types/node@>=10.0.0", "@types/node@>=8.1.0": - version "20.4.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.1.tgz#a6033a8718653c50ac4962977e14d0f984d9527d" - integrity sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg== - -"@types/prettier@^2.1.5": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" - integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== + version "20.4.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.2.tgz#129cc9ae69f93824f92fac653eebfb4812ab4af9" + integrity sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw== "@types/semver@^7.3.12": version "7.5.0" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== -"@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== - "@types/webidl-conversions@*": version "7.0.0" resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz#2b8e60e33906459219aa587e9d1a612ae994cfe7" @@ -1705,38 +1276,26 @@ "@types/node" "*" "@types/webidl-conversions" "*" -"@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== - -"@types/yargs@^17.0.8": - version "17.0.24" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902" - integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw== +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== dependencies: - "@types/yargs-parser" "*" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.61.0.tgz#b670006d069c9abe6415c41f754b1b5d949ef2b2" - integrity sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw== - dependencies: - "@typescript-eslint/types" "5.61.0" - "@typescript-eslint/visitor-keys" "5.61.0" - -"@typescript-eslint/types@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.61.0.tgz#e99ff11b5792d791554abab0f0370936d8ca50c0" - integrity sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ== +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/typescript-estree@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.61.0.tgz#4c7caca84ce95bb41aa585d46a764bcc050b92f3" - integrity sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw== +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== dependencies: - "@typescript-eslint/types" "5.61.0" - "@typescript-eslint/visitor-keys" "5.61.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -1744,25 +1303,25 @@ tsutils "^3.21.0" "@typescript-eslint/utils@^5.10.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.61.0.tgz#5064838a53e91c754fffbddd306adcca3fe0af36" - integrity sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.61.0" - "@typescript-eslint/types" "5.61.0" - "@typescript-eslint/typescript-estree" "5.61.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.61.0.tgz#c79414fa42158fd23bd2bb70952dc5cdbb298140" - integrity sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg== +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== dependencies: - "@typescript-eslint/types" "5.61.0" + "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" abbrev@1: @@ -1820,7 +1379,12 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -1851,17 +1415,12 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - ansi-styles@^6.0.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== -anymatch@^3.0.3, anymatch@~3.1.2: +anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -1874,11 +1433,23 @@ append-field@^1.0.0: resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56" integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw== +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== + dependencies: + default-require-extensions "^3.0.0" + "aproba@^1.0.3 || ^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== + are-we-there-yet@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" @@ -1909,11 +1480,6 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - asn1.js@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -1929,83 +1495,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async-mutex@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.3.2.tgz#1485eda5bda1b0ec7c8df1ac2e815757ad1831df" - integrity sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA== - dependencies: - tslib "^2.3.1" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - atomic-sleep@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== -babel-jest@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.3.tgz#c1187258197c099072156a0a121c11ee1e3917d5" - integrity sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q== - dependencies: - "@jest/transform" "^28.1.3" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^28.1.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz#1952c4d0ea50f2d6d794353762278d1d8cca3fbe" - integrity sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz#5dfc20b99abed5db994406c2b9ab94c73aaa419d" - integrity sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A== - dependencies: - babel-plugin-jest-hoist "^28.1.3" - babel-preset-current-node-syntax "^1.0.0" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -2029,20 +1523,16 @@ bcrypt@^5.0.1: "@mapbox/node-pre-gyp" "^1.0.10" node-addon-api "^5.0.0" +big-integer@^1.6.44: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - bn.js@^4.0.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -2089,6 +1579,13 @@ bowser@^2.11.0: resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== +bplist-parser@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2097,6 +1594,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2104,6 +1608,11 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + browserslist@^4.21.9: version "4.21.9" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" @@ -2114,24 +1623,10 @@ browserslist@^4.21.9: node-releases "^2.0.12" update-browserslist-db "^1.0.11" -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -bson@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/bson/-/bson-4.7.2.tgz#320f4ad0eaf5312dd9b45dc369cc48945e2a5f2e" - integrity sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ== - dependencies: - buffer "^5.6.0" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== +bson@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/bson/-/bson-5.4.0.tgz#0eea77276d490953ad8616b483298dbff07384c6" + integrity sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA== buffer-equal-constant-time@1.0.1: version "1.0.1" @@ -2143,14 +1638,6 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.5.0, buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -2173,6 +1660,13 @@ bull@^4.8.3: semver "^7.3.2" uuid "^8.3.0" +bundle-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" + integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== + dependencies: + run-applescript "^5.0.0" + busboy@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -2185,6 +1679,16 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== + dependencies: + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" + call-bind@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -2203,20 +1707,20 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^5.3.1: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.2.0, camelcase@^6.3.0: +camelcase@^6.0.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001503: - version "1.0.30001513" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001513.tgz#382fe5fbfb0f7abbaf8c55ca3ac71a0307a752e9" - integrity sha512-pnjGJo7SOOjAGytZZ203Em95MRM8Cr6jhCXNF/FAXTpCTRTECnqQWLpiTRqrFtdYcth8hf4WECUpkezuYsMVww== + version "1.0.30001517" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz#90fabae294215c3495807eb24fc809e11dc2f0a8" + integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA== chalk@5.2.0: version "5.2.0" @@ -2232,7 +1736,7 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2240,12 +1744,7 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -chokidar@^3.5.2: +chokidar@3.5.3, chokidar@^3.5.2: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -2265,16 +1764,6 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== -ci-info@^3.2.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" - integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== - -cjs-module-lexer@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== - clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -2303,13 +1792,22 @@ cli-truncate@^3.1.0: slice-ansi "^5.0.0" string-width "^5.0.0" -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: string-width "^4.2.0" - strip-ansi "^6.0.1" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" wrap-ansi "^7.0.0" cluster-key-slot@^1.1.0: @@ -2317,16 +1815,6 @@ cluster-key-slot@^1.1.0: resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== - -collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2361,13 +1849,6 @@ colorette@^2.0.19: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - commander@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" @@ -2383,11 +1864,6 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== -component-emitter@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2403,10 +1879,10 @@ concat-stream@^1.5.2: readable-stream "^2.2.2" typedarray "^0.0.6" -connect-mongo@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/connect-mongo/-/connect-mongo-4.6.0.tgz#1bf62868efc9f28ecf1459ae9a9d6caaf90ae8a6" - integrity sha512-8new4Z7NLP3CGP65Aw6ls3xDBeKVvHRSh39CXuDZTQsvpeeU9oNMzfFgvqmHqZ6gWpxIl663RyoVEmCAGf1yOg== +connect-mongo@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/connect-mongo/-/connect-mongo-5.0.0.tgz#2a902d293d369a4baff2e988634cda6f8c0bf721" + integrity sha512-s93jiP6GkRApn5duComx6RLwtP23YrulPxShz+8peX7svd6Q+MS8nKLhKCCazbP92C13eTVaIOxgeLt0ezIiCg== dependencies: debug "^4.3.1" kruptein "^3.0.0" @@ -2428,7 +1904,7 @@ content-type@~1.0.4, content-type@~1.0.5: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== -convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -2448,11 +1924,6 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -cookiejar@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" - integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -2473,7 +1944,7 @@ cron-parser@^4.2.1: dependencies: luxon "^3.2.1" -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2489,7 +1960,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@4.x, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: +debug@4, debug@4.3.4, debug@4.x, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2508,25 +1979,50 @@ debuglog@^1.0.0: resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw== -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== +default-browser-id@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" + integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== + dependencies: + bplist-parser "^0.2.0" + untildify "^4.0.0" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +default-browser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" + integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== + dependencies: + bundle-name "^3.0.0" + default-browser-id "^3.0.0" + execa "^7.1.1" + titleize "^3.0.0" + +default-require-extensions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.1.tgz#bfae00feeaeada68c2ae256c62540f60b80625bd" + integrity sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw== + dependencies: + strip-bom "^4.0.0" + +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== delegates@^1.0.0: version "1.0.0" @@ -2549,27 +2045,14 @@ destroy@1.2.0: integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-libc@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" - integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -dezalgo@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" - integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== - dependencies: - asap "^2.0.0" - wrappy "1" + version "2.0.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d" + integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== -diff-sequences@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6" - integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw== +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== dir-glob@^3.0.1: version "3.0.1" @@ -2603,20 +2086,15 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.4.431: - version "1.4.454" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.454.tgz#774dc7cb5e58576d0125939ec34a4182f3ccc87d" - integrity sha512-pmf1rbAStw8UEQ0sr2cdJtWl48ZMuPD9Sto8HVQOq9vx9j2WgDEN6lYoaqFvqEHYOmGA9oRGn7LqWI9ta0YugQ== + version "1.4.466" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.466.tgz#17193d70f203da3d52a89c653b8d89f47a51d79d" + integrity sha512-TSkRvbXRXD8BwhcGlZXDsbI2lRoP8dvqR7LQnqQNk9KxXBc4tG8O+rTuXgTyIpEdiqSGKEBSqrxdqEntnjNncA== email-validator@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-2.0.4.tgz#b8dfaa5d0dae28f1b03c95881d904d4e40bfe7ed" integrity sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ== -emittery@^0.10.2: - version "0.10.2" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" - integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -2632,13 +2110,6 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - engine.io-client@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.1.tgz#1735fb8ae3bae5ae13115e18d2f484daf005dd9c" @@ -2671,12 +2142,10 @@ engine.io@~6.5.0: engine.io-parser "~5.1.0" ws "~8.11.0" -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== escalade@^3.1.1: version "3.1.1" @@ -2688,21 +2157,16 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - eslint-config-prettier@^8.5.0: version "8.8.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" @@ -2715,12 +2179,13 @@ eslint-plugin-jest@^26.2.2: dependencies: "@typescript-eslint/utils" "^5.10.0" -eslint-plugin-prettier@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== +eslint-plugin-prettier@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz#6887780ed95f7708340ec79acfdf60c35b9be57a" + integrity sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w== dependencies: prettier-linter-helpers "^1.0.0" + synckit "^0.8.5" eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" @@ -2731,9 +2196,9 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: estraverse "^4.1.1" eslint-scope@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" - integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== + version "7.2.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.1.tgz#936821d3462675f25a18ac5fd88a67cc15b393bd" + integrity sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -2748,10 +2213,10 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== -eslint@^8.15.0: - version "8.44.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.44.0.tgz#51246e3889b259bbcd1d7d736a0c10add4f0e500" - integrity sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A== +eslint@^8.45.0: + version "8.45.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.45.0.tgz#bab660f90d18e1364352c0a6b7c6db8edb458b78" + integrity sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.4.0" @@ -2778,7 +2243,6 @@ eslint@^8.15.0: globals "^13.19.0" graphemer "^1.4.0" ignore "^5.2.0" - import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" @@ -2790,13 +2254,12 @@ eslint@^8.15.0: natural-compare "^1.4.0" optionator "^0.9.3" strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" text-table "^0.2.0" espree@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f" - integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A== + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: acorn "^8.9.0" acorn-jsx "^5.3.2" @@ -2866,7 +2329,7 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^7.0.0: +execa@^7.0.0, execa@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== @@ -2881,22 +2344,6 @@ execa@^7.0.0: signal-exit "^3.0.7" strip-final-newline "^3.0.0" -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== - -expect@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.3.tgz#90a7c1a124f1824133dd4533cce2d2bdcb6603ec" - integrity sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g== - dependencies: - "@jest/expect-utils" "^28.1.3" - jest-get-type "^28.0.2" - jest-matcher-utils "^28.1.3" - jest-message-util "^28.1.3" - jest-util "^28.1.3" - express-session@^1.17.3: version "1.17.3" resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.3.tgz#14b997a15ed43e5949cb1d073725675dd2777f36" @@ -2958,7 +2405,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-glob@^3.2.9: +fast-glob@^3.2.9, fast-glob@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== @@ -2984,11 +2431,6 @@ fast-redact@^3.1.1: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.2.0.tgz#b1e2d39bc731376d28bde844454fa23e26919987" integrity sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw== -fast-safe-stringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - fast-xml-parser@4.2.5: version "4.2.5" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" @@ -3003,20 +2445,6 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== - dependencies: - pend "~1.2.0" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -3044,7 +2472,7 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" -find-cache-dir@^3.3.2: +find-cache-dir@^3.2.0: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== @@ -3053,6 +2481,14 @@ find-cache-dir@^3.3.2: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-up@5.0.0, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -3061,14 +2497,6 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -3077,29 +2505,23 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + flatted@^3.1.0: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -formidable@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.2.tgz#fa973a2bec150e4ce7cac15589d7a25fc30ebd89" - integrity sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g== +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== dependencies: - dezalgo "^1.0.4" - hexoid "^1.0.0" - once "^1.4.0" - qs "^6.11.0" + cross-spawn "^7.0.0" + signal-exit "^3.0.2" forwarded@0.2.0: version "0.2.0" @@ -3111,10 +2533,10 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fromentries@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" + integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== fs-minipass@^2.0.0: version "2.1.0" @@ -3128,12 +2550,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fscreen@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fscreen/-/fscreen-1.2.0.tgz#1a8c88e06bc16a07b473ad96196fb06d6657f59e" - integrity sha512-hlq4+BU0hlPmwsFjwGGzZ+OZ9N/wq9Ljg/sq3pX+2CD7hrJsX9tJgWWK/wiNTFM212CLHWhicOoqwXyZGGetJg== - -fsevents@^2.3.2, fsevents@~2.3.2: +fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== @@ -3163,7 +2580,7 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.5: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -3219,7 +2636,19 @@ glob@7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.4: +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -3255,7 +2684,7 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.2.9: +graceful-fs@^4.1.15: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -3297,10 +2726,18 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hexoid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" - integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== +hasha@^5.0.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== html-escaper@^2.0.0: version "2.0.2" @@ -3318,7 +2755,7 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" -https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: +https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== @@ -3343,7 +2780,7 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -3358,7 +2795,7 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -import-fresh@^3.0.0, import-fresh@^3.2.1: +import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -3366,14 +2803,6 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -3392,7 +2821,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3422,11 +2851,6 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -3434,12 +2858,15 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-core-module@^2.11.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" - integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== - dependencies: - has "^1.0.3" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== is-extglob@^2.1.1: version "2.1.1" @@ -3456,11 +2883,6 @@ is-fullwidth-code-point@^4.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -3468,6 +2890,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -3478,6 +2907,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" @@ -3488,6 +2922,28 @@ is-stream@^3.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -3503,406 +2959,73 @@ istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.5" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" - integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jest-changed-files@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-28.1.3.tgz#d9aeee6792be3686c47cb988a8eaf82ff4238831" - integrity sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA== - dependencies: - execa "^5.0.0" - p-limit "^3.1.0" - -jest-circus@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.3.tgz#d14bd11cf8ee1a03d69902dc47b6bd4634ee00e4" - integrity sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow== - dependencies: - "@jest/environment" "^28.1.3" - "@jest/expect" "^28.1.3" - "@jest/test-result" "^28.1.3" - "@jest/types" "^28.1.3" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - is-generator-fn "^2.0.0" - jest-each "^28.1.3" - jest-matcher-utils "^28.1.3" - jest-message-util "^28.1.3" - jest-runtime "^28.1.3" - jest-snapshot "^28.1.3" - jest-util "^28.1.3" - p-limit "^3.1.0" - pretty-format "^28.1.3" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.3.tgz#558b33c577d06de55087b8448d373b9f654e46b2" - integrity sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ== - dependencies: - "@jest/core" "^28.1.3" - "@jest/test-result" "^28.1.3" - "@jest/types" "^28.1.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^28.1.3" - jest-util "^28.1.3" - jest-validate "^28.1.3" - prompts "^2.0.1" - yargs "^17.3.1" - -jest-config@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.3.tgz#e315e1f73df3cac31447eed8b8740a477392ec60" - integrity sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^28.1.3" - "@jest/types" "^28.1.3" - babel-jest "^28.1.3" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^28.1.3" - jest-environment-node "^28.1.3" - jest-get-type "^28.0.2" - jest-regex-util "^28.0.2" - jest-resolve "^28.1.3" - jest-runner "^28.1.3" - jest-util "^28.1.3" - jest-validate "^28.1.3" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^28.1.3" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.3.tgz#948a192d86f4e7a64c5264ad4da4877133d8792f" - integrity sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw== - dependencies: - chalk "^4.0.0" - diff-sequences "^28.1.1" - jest-get-type "^28.0.2" - pretty-format "^28.1.3" - -jest-docblock@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-28.1.1.tgz#6f515c3bf841516d82ecd57a62eed9204c2f42a8" - integrity sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA== - dependencies: - detect-newline "^3.0.0" - -jest-each@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.3.tgz#bdd1516edbe2b1f3569cfdad9acd543040028f81" - integrity sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g== - dependencies: - "@jest/types" "^28.1.3" - chalk "^4.0.0" - jest-get-type "^28.0.2" - jest-util "^28.1.3" - pretty-format "^28.1.3" - -jest-environment-node@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.3.tgz#7e74fe40eb645b9d56c0c4b70ca4357faa349be5" - integrity sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A== - dependencies: - "@jest/environment" "^28.1.3" - "@jest/fake-timers" "^28.1.3" - "@jest/types" "^28.1.3" - "@types/node" "*" - jest-mock "^28.1.3" - jest-util "^28.1.3" - -jest-get-type@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203" - integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA== - -jest-haste-map@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.3.tgz#abd5451129a38d9841049644f34b034308944e2b" - integrity sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA== - dependencies: - "@jest/types" "^28.1.3" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^28.0.2" - jest-util "^28.1.3" - jest-worker "^28.1.3" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz#a6685d9b074be99e3adee816ce84fd30795e654d" - integrity sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA== - dependencies: - jest-get-type "^28.0.2" - pretty-format "^28.1.3" - -jest-matcher-utils@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz#5a77f1c129dd5ba3b4d7fc20728806c78893146e" - integrity sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw== - dependencies: - chalk "^4.0.0" - jest-diff "^28.1.3" - jest-get-type "^28.0.2" - pretty-format "^28.1.3" - -jest-message-util@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.3.tgz#232def7f2e333f1eecc90649b5b94b0055e7c43d" - integrity sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^28.1.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^28.1.3" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.3.tgz#d4e9b1fc838bea595c77ab73672ebf513ab249da" - integrity sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA== - dependencies: - "@jest/types" "^28.1.3" - "@types/node" "*" - -jest-pnp-resolver@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== - -jest-regex-util@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead" - integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw== - -jest-resolve-dependencies@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz#8c65d7583460df7275c6ea2791901fa975c1fe66" - integrity sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA== - dependencies: - jest-regex-util "^28.0.2" - jest-snapshot "^28.1.3" - -jest-resolve@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.3.tgz#cfb36100341ddbb061ec781426b3c31eb51aa0a8" - integrity sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^28.1.3" - jest-pnp-resolver "^1.2.2" - jest-util "^28.1.3" - jest-validate "^28.1.3" - resolve "^1.20.0" - resolve.exports "^1.1.0" - slash "^3.0.0" - -jest-runner@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.3.tgz#5eee25febd730b4713a2cdfd76bdd5557840f9a1" - integrity sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA== - dependencies: - "@jest/console" "^28.1.3" - "@jest/environment" "^28.1.3" - "@jest/test-result" "^28.1.3" - "@jest/transform" "^28.1.3" - "@jest/types" "^28.1.3" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.10.2" - graceful-fs "^4.2.9" - jest-docblock "^28.1.1" - jest-environment-node "^28.1.3" - jest-haste-map "^28.1.3" - jest-leak-detector "^28.1.3" - jest-message-util "^28.1.3" - jest-resolve "^28.1.3" - jest-runtime "^28.1.3" - jest-util "^28.1.3" - jest-watcher "^28.1.3" - jest-worker "^28.1.3" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.3.tgz#a57643458235aa53e8ec7821949e728960d0605f" - integrity sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw== - dependencies: - "@jest/environment" "^28.1.3" - "@jest/fake-timers" "^28.1.3" - "@jest/globals" "^28.1.3" - "@jest/source-map" "^28.1.2" - "@jest/test-result" "^28.1.3" - "@jest/transform" "^28.1.3" - "@jest/types" "^28.1.3" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - execa "^5.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^28.1.3" - jest-message-util "^28.1.3" - jest-mock "^28.1.3" - jest-regex-util "^28.0.2" - jest-resolve "^28.1.3" - jest-snapshot "^28.1.3" - jest-util "^28.1.3" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.3.tgz#17467b3ab8ddb81e2f605db05583d69388fc0668" - integrity sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^28.1.3" - "@jest/transform" "^28.1.3" - "@jest/types" "^28.1.3" - "@types/babel__traverse" "^7.0.6" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^28.1.3" - graceful-fs "^4.2.9" - jest-diff "^28.1.3" - jest-get-type "^28.0.2" - jest-haste-map "^28.1.3" - jest-matcher-utils "^28.1.3" - jest-message-util "^28.1.3" - jest-util "^28.1.3" - natural-compare "^1.4.0" - pretty-format "^28.1.3" - semver "^7.3.5" +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" -jest-util@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.3.tgz#f4f932aa0074f0679943220ff9cbba7e497028b0" - integrity sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ== +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== dependencies: - "@jest/types" "^28.1.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" -jest-validate@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.3.tgz#e322267fd5e7c64cea4629612c357bbda96229df" - integrity sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA== +istanbul-lib-processinfo@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz#366d454cd0dcb7eb6e0e419378e60072c8626169" + integrity sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg== dependencies: - "@jest/types" "^28.1.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^28.0.2" - leven "^3.1.0" - pretty-format "^28.1.3" + archy "^1.0.0" + cross-spawn "^7.0.3" + istanbul-lib-coverage "^3.2.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^8.3.2" -jest-watcher@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.3.tgz#c6023a59ba2255e3b4c57179fc94164b3e73abd4" - integrity sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g== +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== dependencies: - "@jest/test-result" "^28.1.3" - "@jest/types" "^28.1.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.10.2" - jest-util "^28.1.3" - string-length "^4.0.1" + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" -jest-worker@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.3.tgz#7e3c4ce3fa23d1bb6accb169e7f396f98ed4bb98" - integrity sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g== +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" -jest@^28.1.0: - version "28.1.3" - resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.3.tgz#e9c6a7eecdebe3548ca2b18894a50f45b36dfc6b" - integrity sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA== +istanbul-reports@^3.0.2: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== dependencies: - "@jest/core" "^28.1.3" - "@jest/types" "^28.1.3" - import-local "^3.0.2" - jest-cli "^28.1.3" + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@4.1.0, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -3911,23 +3034,11 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -3943,21 +3054,15 @@ json5@^2.2.2: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsonwebtoken@^8.5.1: - version "8.5.1" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" - integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== +jsonwebtoken@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz#81d8c901c112c24e497a55daf6b2be1225b40145" + integrity sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg== dependencies: jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" + lodash "^4.17.21" ms "^2.1.1" - semver "^5.6.0" + semver "^7.3.8" jwa@^1.4.1: version "1.4.1" @@ -3981,11 +3086,6 @@ kareem@2.5.1: resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.5.1.tgz#7b8203e11819a8e77a34b3517d3ead206764d15d" integrity sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA== -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - kruptein@^3.0.0: version "3.0.6" resolved "https://registry.yarnpkg.com/kruptein/-/kruptein-3.0.6.tgz#9cf976225af4bc1fbeba069dbb24f17eebad974d" @@ -3993,11 +3093,6 @@ kruptein@^3.0.0: dependencies: asn1.js "^5.4.1" -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -4011,11 +3106,6 @@ lilconfig@2.1.0: resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - lint-staged@^13.0.0: version "13.2.3" resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.3.tgz#f899aad6c093473467e9c9e316e3c2d8a28f87a7" @@ -4068,51 +3158,26 @@ lodash.defaults@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ== + lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== - lodash.isarguments@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== - lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== - lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -4123,16 +3188,19 @@ lodash.mergewith@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== - lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + log-update@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" @@ -4169,18 +3237,6 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: dependencies: semver "^6.0.0" -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -md5-file@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-5.0.0.tgz#e519f631feca9c39e7f9ea1780b63c4745012e20" - integrity sha512-xbEFXCYVWrSx/gEKS1VPlg84h/4L20znVIulKw6kMfmBUAZNAnF00eczz9ICMl+/hjQGo5KSXRxbL/47X3rmMw== - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -4206,7 +3262,7 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@^1.1.2, methods@~1.1.2: +methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== @@ -4224,7 +3280,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -4236,11 +3292,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mime@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" @@ -4269,6 +3320,13 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -4313,7 +3371,34 @@ mkdirp@^1.0.3: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mongodb-connection-string-url@^2.5.4: +mocha@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +mongodb-connection-string-url@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz#57901bf352372abdde812c81be47b75c6b2ec5cf" integrity sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ== @@ -4321,56 +3406,27 @@ mongodb-connection-string-url@^2.5.4: "@types/whatwg-url" "^8.2.1" whatwg-url "^11.0.0" -mongodb-memory-server-core@8.13.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/mongodb-memory-server-core/-/mongodb-memory-server-core-8.13.0.tgz#3aabf0faa2ad0eaf986dd047bfb9d599a285d4ed" - integrity sha512-4NTOzYOlRUilwb8CxOKix/XbZmac4cLpmEU03eaHx90lgEp+ARZM2PQtIOEg3nhHo97r9THIEv6Gs4LECokp0Q== +mongodb@5.7.0, mongodb@^5.7.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-5.7.0.tgz#e16d2fcdfd9f8503ec2d88288392dc3235bb3ecc" + integrity sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw== dependencies: - async-mutex "^0.3.2" - camelcase "^6.3.0" - debug "^4.3.4" - find-cache-dir "^3.3.2" - get-port "^5.1.1" - https-proxy-agent "^5.0.1" - md5-file "^5.0.0" - mongodb "^4.16.0" - new-find-package-json "^2.0.0" - semver "^7.5.1" - tar-stream "^2.1.4" - tslib "^2.5.3" - uuid "^9.0.0" - yauzl "^2.10.0" - -mongodb-memory-server@^8.6.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/mongodb-memory-server/-/mongodb-memory-server-8.13.0.tgz#c3302c72972220f2d7f8e48dc1919eb75c8585a8" - integrity sha512-CyrKMwEmRePn8iQ3LtWQiOJxlGK0eM+NNTq3Yg8m7gaywepFu24mF7s13q87Kfuq0WgBuCJQ4t6VcUZJ4m+KWQ== - dependencies: - mongodb-memory-server-core "8.13.0" - tslib "^2.5.3" - -mongodb@4.16.0, mongodb@^4.16.0: - version "4.16.0" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.16.0.tgz#8b0043de7b577c6a7e0ce44a2ca7315b9c0a7927" - integrity sha512-0EB113Fsucaq1wsY0dOhi1fmZOwFtLOtteQkiqOXGklvWMnSH3g2QS53f0KTP+/6qOkuoXE2JksubSZNmxeI+g== - dependencies: - bson "^4.7.2" - mongodb-connection-string-url "^2.5.4" + bson "^5.4.0" + mongodb-connection-string-url "^2.6.0" socks "^2.7.1" optionalDependencies: - "@aws-sdk/credential-providers" "^3.186.0" saslprep "^1.0.3" -mongoose@^6.3.3: - version "6.11.2" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.11.2.tgz#29b4933de3bcbbd5ebd5e3d979791d827f9d527e" - integrity sha512-BJHQerozE+qIVdH8Hn9niMVMUzRNcjmwU7hFEzER1+aYtGmVJgGsXBd9wJ9GnrHrbCsYmKlRy8aTuxEdlEtfow== +mongoose@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-7.4.0.tgz#3726a8dea0c9e2d54651845cc84c813a6507906a" + integrity sha512-oHE1eqodfKzugXRlQxpo+msIea7jPcRoayDuEMr50+bYwM/juA5f+1stjkWlXcg6vo1PdJFVA6DGaKOPLuG5mA== dependencies: - bson "^4.7.2" + bson "^5.4.0" kareem "2.5.1" - mongodb "4.16.0" + mongodb "5.7.0" mpath "0.9.0" - mquery "4.0.3" + mquery "5.0.0" ms "2.1.3" sift "16.0.1" @@ -4379,10 +3435,10 @@ mpath@0.9.0: resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.9.0.tgz#0c122fe107846e31fc58c75b09c35514b3871904" integrity sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew== -mquery@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/mquery/-/mquery-4.0.3.tgz#4d15f938e6247d773a942c912d9748bd1965f89d" - integrity sha512-J5heI+P08I6VJ2Ky3+33IpCdAvlYGTSUjwTPxkAr8i8EoduPMBX2OY/wa3IKZIQl7MU4SbFk8ndgSKyB/cl1zA== +mquery@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/mquery/-/mquery-5.0.0.tgz#a95be5dfc610b23862df34a47d3e5d60e110695d" + integrity sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg== dependencies: debug "4.x" @@ -4435,6 +3491,11 @@ multer@^1.4.5-lts.1: type-is "^1.6.4" xtend "^4.0.0" +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -4445,13 +3506,6 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -new-find-package-json@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/new-find-package-json/-/new-find-package-json-2.0.0.tgz#96553638781db35061f351e8ccb4d07126b6407d" - integrity sha512-lDcBsjBSMlj3LXH2v/FW3txlh2pYTjmbOXPYJD93HI5EwuLzI11tdHSIpUMmfq/IOsldj4Ps8M8flhm+pCK4Ew== - dependencies: - debug "^4.3.4" - node-addon-api@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" @@ -4469,28 +3523,30 @@ node-gyp-build-optional-packages@5.0.7: resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz#5d2632bbde0ab2f6e22f1bbac2199b07244ae0b3" integrity sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w== -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== +node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" node-releases@^2.0.12: version "2.0.13" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== -nodemon@^2.0.16: - version "2.0.22" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.22.tgz#182c45c3a78da486f673d6c1702e00728daf5258" - integrity sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ== +nodemon@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.1.tgz#affe822a2c5f21354466b2fc8ae83277d27dadc7" + integrity sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw== dependencies: chokidar "^3.5.2" debug "^3.2.7" ignore-by-default "^1.0.1" minimatch "^3.1.2" pstree.remy "^1.1.8" - semver "^5.7.1" - simple-update-notifier "^1.0.7" + semver "^7.5.3" + simple-update-notifier "^2.0.0" supports-color "^5.5.0" touch "^3.1.0" undefsafe "^2.0.5" @@ -4538,6 +3594,39 @@ npmlog@^5.0.1: gauge "^3.0.0" set-blocking "^2.0.0" +nyc@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== + dependencies: + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + get-package-type "^0.1.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" + object-assign@^4, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -4565,7 +3654,7 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== -once@^1.3.0, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -4586,6 +3675,16 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +open@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" + integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== + dependencies: + default-browser "^4.0.0" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^2.2.0" + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -4605,7 +3704,7 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -4626,6 +3725,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -4638,6 +3744,16 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -4645,16 +3761,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -4701,11 +3807,6 @@ path-key@^4.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -4721,17 +3822,12 @@ pause@0.0.1: resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -4781,12 +3877,7 @@ pino@^8.0.0, pino@^8.14.1: sonic-boom "^3.1.0" thread-stream "^2.0.0" -pirates@^4.0.4: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pkg-dir@^4.1.0, pkg-dir@^4.2.0: +pkg-dir@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -4805,26 +3896,23 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.6.2: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - -pretty-format@^28.1.3: - version "28.1.3" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.3.tgz#c9fba8cedf99ce50963a11b27d982a9ae90970d5" - integrity sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q== - dependencies: - "@jest/schemas" "^28.1.3" - ansi-regex "^5.0.1" - ansi-styles "^5.0.0" - react-is "^18.0.0" +prettier@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.0.tgz#e7b19f691245a21d618c68bc54dc06122f6105ae" + integrity sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g== process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + process-warning@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626" @@ -4835,14 +3923,6 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -4868,7 +3948,7 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" -qs@^6.10.3, qs@^6.11.0: +qs@^6.10.3: version "6.11.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== @@ -4895,6 +3975,13 @@ random-string@^0.2.0: resolved "https://registry.yarnpkg.com/random-string/-/random-string-0.2.0.tgz#a46e4375352beda9a0d7b0d19ed6d321ecd1d82d" integrity sha512-isA91IquV3ZrFbvwkAtExP8aGL+csx3KGEsEJrvCidzOHioPl5B5g7WyJlk0lMkEz5/i1PqrWTvcdtJHPtrp1g== +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -4920,18 +4007,6 @@ raw-body@2.5.2: iconv-lite "0.4.24" unpipe "1.0.0" -react-full-screen@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/react-full-screen/-/react-full-screen-1.1.1.tgz#b707d56891015a71c503a65dbab3086d75be97d7" - integrity sha512-xoEgkoTiN0dw9cjYYGViiMCBYbkS97BYb4bHPhQVWXj1UnOs8PZ1rPzpX+2HMhuvQV1jA5AF9GaRbO3fA5aZtg== - dependencies: - fscreen "^1.0.2" - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - readable-stream@^2.2.2: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" @@ -4945,7 +4020,7 @@ readable-stream@^2.2.2: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -4989,17 +4064,22 @@ redis-parser@^3.0.0: dependencies: redis-errors "^1.0.0" +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA== + dependencies: + es6-error "^4.0.1" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== resolve-from@^4.0.0: version "4.0.0" @@ -5011,20 +4091,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve.exports@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999" - integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ== - -resolve@^1.20.0: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== - dependencies: - is-core-module "^2.11.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -5050,6 +4116,13 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +run-applescript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" + integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== + dependencies: + execa "^5.0.0" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -5064,7 +4137,7 @@ rxjs@^7.8.0: dependencies: tslib "^2.1.0" -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5091,28 +4164,23 @@ saslprep@^1.0.3: dependencies: sparse-bitfield "^3.0.3" -semver@^5.6.0, semver@^5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.1: +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" -semver@~7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -5132,6 +4200,13 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + serve-static@1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" @@ -5183,17 +4258,12 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -simple-update-notifier@^1.0.7: - version "1.1.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" - integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== +simple-update-notifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== dependencies: - semver "~7.0.0" - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + semver "^7.5.3" slash@^3.0.0: version "3.0.0" @@ -5284,15 +4354,7 @@ sonic-boom@^3.1.0: dependencies: atomic-sleep "^1.0.0" -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1: +source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -5304,6 +4366,18 @@ sparse-bitfield@^3.0.3: dependencies: memory-pager "^1.0.2" +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== + dependencies: + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + which "^2.0.1" + split2@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" @@ -5314,13 +4388,6 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - standard-as-callback@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" @@ -5341,14 +4408,6 @@ string-argv@^0.3.1: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -5410,7 +4469,7 @@ strip-final-newline@^3.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -5428,29 +4487,12 @@ strnum@^1.0.5: resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== -superagent@^8.0.5: - version "8.0.9" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.0.9.tgz#2c6fda6fadb40516515f93e9098c0eb1602e0535" - integrity sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA== - dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.4" - debug "^4.3.4" - fast-safe-stringify "^2.1.1" - form-data "^4.0.0" - formidable "^2.1.2" - methods "^1.1.2" - mime "2.6.0" - qs "^6.11.0" - semver "^7.3.8" - -supertest@^6.2.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.3.tgz#42f4da199fee656106fd422c094cf6c9578141db" - integrity sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA== +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: - methods "^1.1.2" - superagent "^8.0.5" + has-flag "^4.0.0" supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" @@ -5459,33 +4501,13 @@ supports-color@^5.3.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^7.0.0, supports-color@^7.1.0: +supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-hyperlinks@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" - integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== - dependencies: - has-flag "^4.0.0" - supports-color "^7.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - swagger-jsdoc@^6.2.1: version "6.2.8" resolved "https://registry.yarnpkg.com/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz#6d33d9fb07ff4a7c1564379c52c08989ec7d0256" @@ -5506,9 +4528,9 @@ swagger-parser@^10.0.3: "@apidevtools/swagger-parser" "10.0.3" swagger-ui-dist@>=4.11.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-5.1.0.tgz#b01b3be06bebb2566b2df586c1632d502ec792ad" - integrity sha512-c1KmAjuVODxw+vwkNLALQZrgdlBAuBbr2xSPfYrJgseEi7gFKcTvShysPmyuDI4kcUa1+5rFpjWvXdusKY74mg== + version "5.1.3" + resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-5.1.3.tgz#2f9437b08454a07f87d2672cf28f045fb30b10c7" + integrity sha512-W/vZFeZHG+xTN4yu8LXdaIrcnT4Hbr7qRUILYlMEoIiG6nuTylnEGeRcvL64F2eHRA2Jo/fgCSTU06Qfh0lT3g== swagger-ui-express@^4.4.0: version "4.6.3" @@ -5517,16 +4539,13 @@ swagger-ui-express@^4.4.0: dependencies: swagger-ui-dist ">=4.11.0" -tar-stream@^2.1.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== +synckit@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3" + integrity sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q== dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" + "@pkgr/utils" "^2.3.1" + tslib "^2.5.0" tar@^6.1.11: version "6.1.15" @@ -5540,14 +4559,6 @@ tar@^6.1.11: mkdirp "^1.0.3" yallist "^4.0.0" -terminal-link@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" - integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== - dependencies: - ansi-escapes "^4.2.1" - supports-hyperlinks "^2.0.0" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -5574,10 +4585,10 @@ through@^2.3.8: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== +titleize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" + integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== to-fast-properties@^2.0.0: version "2.0.0" @@ -5620,7 +4631,7 @@ tslib@^1.11.1, tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0, tslib@^2.3.1, tslib@^2.5.0, tslib@^2.5.3: +tslib@^2.1.0, tslib@^2.3.1, tslib@^2.5.0, tslib@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== @@ -5639,11 +4650,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -5654,6 +4660,11 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^0.8.0: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-is@^1.6.4, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -5662,6 +4673,13 @@ type-is@^1.6.4, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -5684,6 +4702,11 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + update-browserslist-db@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" @@ -5714,20 +4737,6 @@ uuid@^8.3.0, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -uuid@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" - integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== - -v8-to-istanbul@^9.0.1: - version "9.1.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz#1b83ed4e397f58c85c266a570fc2558b5feb9265" - integrity sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" - validator@^13.7.0: version "13.9.0" resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" @@ -5738,13 +4747,6 @@ vary@^1, vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -5771,6 +4773,11 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -5785,6 +4792,11 @@ wide-align@^1.1.2: dependencies: string-width "^1.0.2 || 2 || 3 || 4" +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -5808,13 +4820,15 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== dependencies: imurmurhash "^0.1.4" - signal-exit "^3.0.7" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" ws@~8.11.0: version "8.11.0" @@ -5831,6 +4845,11 @@ xtend@^4.0.0: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -5856,31 +4875,63 @@ yaml@^2.2.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" -yargs@^17.3.1: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: - cliui "^8.0.1" + cliui "^7.0.2" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.3" + string-width "^4.2.0" y18n "^5.0.5" - yargs-parser "^21.1.1" + yargs-parser "^20.2.2" -yauzl@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== +yargs@^15.0.2: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" yocto-queue@^0.1.0: version "0.1.0" diff --git a/yarn.lock b/yarn.lock index 7cc87b93..ac5f7abe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -63,7 +63,12 @@ braces@^3.0.2: dependencies: fill-range "^7.0.1" -chalk@^4.1.0: +chalk@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" + integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== + +chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -120,30 +125,30 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^2.0.16: +colorette@^2.0.19: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -commander@^9.3.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" - integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== -concurrently@^7.1.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.6.0.tgz#531a6f5f30cf616f355a4afb8f8fcb2bba65a49a" - integrity sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw== +concurrently@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-8.2.0.tgz#cdc9f621a4d913366600355d68254df2c5e782f3" + integrity sha512-nnLMxO2LU492mTUj9qX/az/lESonSZu81UznYDoXtz1IQf996ixVqPAgHXwvHiHCAef/7S8HIK+fTFK7Ifk8YA== dependencies: - chalk "^4.1.0" - date-fns "^2.29.1" + chalk "^4.1.2" + date-fns "^2.30.0" lodash "^4.17.21" - rxjs "^7.0.0" - shell-quote "^1.7.3" - spawn-command "^0.0.2-1" - supports-color "^8.1.0" + rxjs "^7.8.1" + shell-quote "^1.8.1" + spawn-command "0.0.2" + supports-color "^8.1.1" tree-kill "^1.2.2" - yargs "^17.3.1" + yargs "^17.7.2" cross-spawn@^7.0.3: version "7.0.3" @@ -154,7 +159,7 @@ cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -date-fns@^2.29.1: +date-fns@^2.30.0: version "2.30.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== @@ -204,20 +209,20 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -execa@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== +execa@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" + integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== dependencies: cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" fill-range@^7.0.1: version "7.0.1" @@ -226,17 +231,12 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -fscreen@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fscreen/-/fscreen-1.2.0.tgz#1a8c88e06bc16a07b473ad96196fb06d6657f59e" - integrity sha512-hlq4+BU0hlPmwsFjwGGzZ+OZ9N/wq9Ljg/sq3pX+2CD7hrJsX9tJgWWK/wiNTFM212CLHWhicOoqwXyZGGetJg== - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stream@^6.0.0: +get-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== @@ -246,10 +246,10 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== husky@^8.0.0: version "8.0.3" @@ -276,65 +276,54 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -lilconfig@2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25" - integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg== +lilconfig@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== -lint-staged@^12.4.1: - version "12.5.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.5.0.tgz#d6925747480ae0e380d13988522f9dd8ef9126e3" - integrity sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g== +lint-staged@^13.2.3: + version "13.2.3" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.3.tgz#f899aad6c093473467e9c9e316e3c2d8a28f87a7" + integrity sha512-zVVEXLuQIhr1Y7R7YAWx4TZLdvuzk7DnmrsTNL0fax6Z3jrpFcas+vKbzxhhvp6TA55m1SQuWkpzI1qbfDZbAg== dependencies: + chalk "5.2.0" cli-truncate "^3.1.0" - colorette "^2.0.16" - commander "^9.3.0" + commander "^10.0.0" debug "^4.3.4" - execa "^5.1.1" - lilconfig "2.0.5" - listr2 "^4.0.5" + execa "^7.0.0" + lilconfig "2.1.0" + listr2 "^5.0.7" micromatch "^4.0.5" normalize-path "^3.0.0" - object-inspect "^1.12.2" - pidtree "^0.5.0" + object-inspect "^1.12.3" + pidtree "^0.6.0" string-argv "^0.3.1" - supports-color "^9.2.2" - yaml "^1.10.2" + yaml "^2.2.2" -listr2@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" - integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== +listr2@^5.0.7: + version "5.0.8" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" + integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA== dependencies: cli-truncate "^2.1.0" - colorette "^2.0.16" + colorette "^2.0.19" log-update "^4.0.0" p-map "^4.0.0" rfdc "^1.3.0" - rxjs "^7.5.5" + rxjs "^7.8.0" through "^2.3.8" wrap-ansi "^7.0.0" -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== - -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== - lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -368,6 +357,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -378,25 +372,32 @@ normalize-path@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== dependencies: - path-key "^3.0.0" + path-key "^4.0.0" -object-inspect@^1.12.2: +object-inspect@^1.12.3: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -404,40 +405,25 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -path-key@^3.0.0, path-key@^3.1.0: +path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pidtree@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.5.0.tgz#ad5fbc1de78b8a5f99d6fbdd4f6e4eee21d1aca1" - integrity sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA== - -react-full-screen@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/react-full-screen/-/react-full-screen-1.1.1.tgz#b707d56891015a71c503a65dbab3086d75be97d7" - integrity sha512-xoEgkoTiN0dw9cjYYGViiMCBYbkS97BYb4bHPhQVWXj1UnOs8PZ1rPzpX+2HMhuvQV1jA5AF9GaRbO3fA5aZtg== - dependencies: - fscreen "^1.0.2" - -react-lazy-load-image-component@^1.5.5: - version "1.6.0" - resolved "https://registry.yarnpkg.com/react-lazy-load-image-component/-/react-lazy-load-image-component-1.6.0.tgz#f262c2f163052d71011e282031fd60aafa6494ac" - integrity sha512-8KFkDTgjh+0+PVbH+cx0AgxLGbdTsxWMnxXzU5HEUztqewk9ufQAu8cstjZhyvtMIPsdMcPZfA0WAa7HtjQbBQ== - dependencies: - lodash.debounce "^4.0.8" - lodash.throttle "^4.1.1" - -react-lazyload@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-lazyload/-/react-lazyload-3.2.0.tgz#497bd06a6dbd7015e3376e1137a67dc47d2dd021" - integrity sha512-zJlrG8QyVZz4+xkYZH5v1w3YaP5wEFaYSUWC4CT9UXfK75IfRAIEdnyIUF+dXr3kX2MOtL1lUaZmaQZqrETwgw== +pidtree@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== regenerator-runtime@^0.13.11: version "0.13.11" @@ -462,7 +448,7 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rxjs@^7.0.0, rxjs@^7.5.5: +rxjs@^7.8.0, rxjs@^7.8.1: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== @@ -481,12 +467,12 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.7.3: +shell-quote@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== -signal-exit@^3.0.2, signal-exit@^3.0.3: +signal-exit@^3.0.2, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -535,10 +521,10 @@ socket.io-parser@~4.2.4: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" -spawn-command@^0.0.2-1: - version "0.0.2-1" - resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" - integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg== +spawn-command@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" + integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== string-argv@^0.3.1: version "0.3.2" @@ -577,10 +563,10 @@ strip-ansi@^7.0.1: dependencies: ansi-regex "^6.0.1" -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== supports-color@^7.1.0: version "7.2.0" @@ -589,18 +575,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.1.0: +supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" -supports-color@^9.2.2: - version "9.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" - integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw== - through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -668,17 +649,17 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yaml@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.2.2: + version "2.3.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" + integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.3.1: +yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==