From a1eb47adb69105be2d301ef1cafc49fc7276eba1 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Wed, 24 Apr 2024 17:20:44 +1000 Subject: [PATCH 01/92] implemented friend group modal --- client/src/components/navbar/Navbar.tsx | 2 + .../src/components/sidebar/AddGroupButton.tsx | 219 ++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 client/src/components/sidebar/AddGroupButton.tsx diff --git a/client/src/components/navbar/Navbar.tsx b/client/src/components/navbar/Navbar.tsx index 8d1187d21..1fc89e982 100644 --- a/client/src/components/navbar/Navbar.tsx +++ b/client/src/components/navbar/Navbar.tsx @@ -12,6 +12,7 @@ import Changelog from './Changelog'; import CustomModal from './CustomModal'; import Privacy from './Privacy'; import Settings from './Settings'; +import AddGroupButton from '../sidebar/AddGroupButton'; const LogoImg = styled('img')` height: 46px; @@ -82,6 +83,7 @@ const Navbar: React.FC = () => { content={} /> } description={'Settings'} content={} /> + diff --git a/client/src/components/sidebar/AddGroupButton.tsx b/client/src/components/sidebar/AddGroupButton.tsx new file mode 100644 index 000000000..72d146575 --- /dev/null +++ b/client/src/components/sidebar/AddGroupButton.tsx @@ -0,0 +1,219 @@ +import { + Close, + Add as AddIcon, + NotesOutlined, + Edit as EditIcon, + CheckCircle as CheckCircleIcon, + RadioButtonUnchecked as RadioButtonUncheckedIcon, +} from '@mui/icons-material'; +import { + Autocomplete, + Button, + Checkbox, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + IconButton, + InputAdornment, + TextField, + Tooltip, + Typography, +} from '@mui/material'; +import { styled } from '@mui/system'; +import React, { useState } from 'react'; + +const StyledDialogTitle = styled(DialogTitle)` + background-color: ${({ theme }) => theme.palette.background.paper}; // darkmode + margin: 0; + padding: 20px; +`; + +const StyledDialogActions = styled(DialogActions)` + background-color: ${({ theme }) => theme.palette.background.paper}; // darkmode +`; + +const CloseButton = styled(IconButton)` + position: absolute; + right: 10px; + top: 10px; +`; + +const StyledTypography = styled(Typography)` + margin-top: 10px; + margin-bottom: 10px; +`; + +const ShowModalButton = styled(IconButton)` + margin-right: 5px; +`; + +const StyledDialogContent = styled(DialogContent)` + background-color: ${({ theme }) => theme.palette.background.paper}; + padding: 20px; + margin-top: 20px; + gap: 20px; + display: flex; + flex-direction: column; + align-items: center; +`; + +const CircleOutline = styled('div')` + width: 150px; + height: 150px; + border-radius: 999px; + border: 0.5px solid black; + cursor: pointer; +`; + +const EditCircleLabel = styled('label')` + background-color: white; + border: 0.5px solid black; + border-radius: 999px; + width: 35px; + height: 35px; + display: flex; + justify-content: center; + align-items: center; + position: relative; + top: -35px; + &:hover { + cursor: pointer; + } +`; + +interface HiddenUploadFileProps { + setSelectedFileImage: (file: null | File) => void; +} + +const HiddenUploadFile: React.FC = ({ setSelectedFileImage }) => { + return ( + { + if (event?.target?.files) { + if (event?.target?.files.length === 0) return; + setSelectedFileImage(event.target.files[0]); + } + }} + /> + ); +}; + +const AddGroupButton = () => { + const [isOpen, setIsOpen] = useState(false); + const [groupName, setGroupName] = useState(''); + const [selectedMembers, setSelectedMembers] = useState([]); + const [selectedFileImage, setSelectedFileImage] = useState(null); + + const handleCreateGroup = () => { + // TODO call API + }; + + const handleClose = () => { + setIsOpen(false); + setGroupName(''); + setSelectedMembers([]); + setSelectedFileImage(null); + }; + + return ( + <> + {/** + Button **/} + + setIsOpen(true)}> + + + + + + + Create a Group + + + + + + +
+ + + + + +
+ setGroupName(e.target.value)} + /> + + setSelectedMembers(value)} + getOptionLabel={(option) => option.name} + renderOption={(props, option, { selected }) => ( +
  • + } + checkedIcon={} + style={{ marginRight: 8 }} + checked={selected} + /> + {option.name} +
  • + )} + renderInput={(params) => } + /> +
    + + {/** FOOTER BUTTONS **/} + + + + +
    + + ); +}; + +/******* DUMMY FRIENDS DATABASE *******/ +interface FriendsType { + name: string; + zID: number; +} + +const friends: FriendsType[] = [ + { name: 'Shaam', zID: 1 }, + { name: 'Ray', zID: 2 }, + { name: 'hhlu', zID: 3 }, + { name: 'Sohum', zID: 4 }, + { name: 'Chanel', zID: 5 }, + { name: 'Nikki', zID: 6 }, + { name: 'Micky', zID: 7 }, + { name: 'Jasmine', zID: 8 }, +]; + +export default AddGroupButton; From 19d360fea272e2af9176996df9e6f09fafd07464 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Wed, 24 Apr 2024 21:03:52 +1000 Subject: [PATCH 02/92] customized chip selected --- .../src/components/sidebar/AddGroupButton.tsx | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/client/src/components/sidebar/AddGroupButton.tsx b/client/src/components/sidebar/AddGroupButton.tsx index 72d146575..b6d6028cc 100644 --- a/client/src/components/sidebar/AddGroupButton.tsx +++ b/client/src/components/sidebar/AddGroupButton.tsx @@ -10,6 +10,7 @@ import { Autocomplete, Button, Checkbox, + Chip, Dialog, DialogActions, DialogContent, @@ -105,7 +106,7 @@ const HiddenUploadFile: React.FC = ({ setSelectedFileImag const AddGroupButton = () => { const [isOpen, setIsOpen] = useState(false); const [groupName, setGroupName] = useState(''); - const [selectedMembers, setSelectedMembers] = useState([]); + const [selectedFriends, setSelectedFriends] = useState([]); const [selectedFileImage, setSelectedFileImage] = useState(null); const handleCreateGroup = () => { @@ -115,10 +116,14 @@ const AddGroupButton = () => { const handleClose = () => { setIsOpen(false); setGroupName(''); - setSelectedMembers([]); + setSelectedFriends([]); setSelectedFileImage(null); }; + const handleDeleteSelectedMember = (zID: number) => { + setSelectedFriends(selectedFriends.filter((friend) => friend.zID !== zID)); + } + return ( <> {/** + Button **/} @@ -127,7 +132,7 @@ const AddGroupButton = () => { - + Create a Group @@ -168,7 +173,7 @@ const AddGroupButton = () => { options={friends} disableCloseOnSelect fullWidth - onChange={(_, value) => setSelectedMembers(value)} + onChange={(_, value) => setSelectedFriends(value)} getOptionLabel={(option) => option.name} renderOption={(props, option, { selected }) => (
  • @@ -178,9 +183,12 @@ const AddGroupButton = () => { style={{ marginRight: 8 }} checked={selected} /> - {option.name} + {option.name} {option.zID}
  • )} + renderTags={(list) => { + return list.map((friend) => console.log(e)}/>) + }} renderInput={(params) => } /> From 449997b984ad03a0336844e949591490b77b4012 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Wed, 24 Apr 2024 21:21:42 +1000 Subject: [PATCH 03/92] added tooltip for tags on selected friends --- .../src/components/sidebar/AddGroupButton.tsx | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/client/src/components/sidebar/AddGroupButton.tsx b/client/src/components/sidebar/AddGroupButton.tsx index b6d6028cc..7c67eba03 100644 --- a/client/src/components/sidebar/AddGroupButton.tsx +++ b/client/src/components/sidebar/AddGroupButton.tsx @@ -122,7 +122,7 @@ const AddGroupButton = () => { const handleDeleteSelectedMember = (zID: number) => { setSelectedFriends(selectedFriends.filter((friend) => friend.zID !== zID)); - } + }; return ( <> @@ -183,11 +183,15 @@ const AddGroupButton = () => { style={{ marginRight: 8 }} checked={selected} /> - {option.name} {option.zID} + {option.name} )} - renderTags={(list) => { - return list.map((friend) => console.log(e)}/>) + renderTags={(tagValue, getTagProps) => { + return tagValue.map((option, index) => ( + + + + )); }} renderInput={(params) => } /> @@ -214,14 +218,14 @@ interface FriendsType { } const friends: FriendsType[] = [ - { name: 'Shaam', zID: 1 }, - { name: 'Ray', zID: 2 }, - { name: 'hhlu', zID: 3 }, - { name: 'Sohum', zID: 4 }, - { name: 'Chanel', zID: 5 }, - { name: 'Nikki', zID: 6 }, - { name: 'Micky', zID: 7 }, - { name: 'Jasmine', zID: 8 }, + { name: 'Shaam', zID: 532445 }, + { name: 'Ray', zID: 523495 }, + { name: 'hhlu', zID: 584290 }, + { name: 'Sohum', zID: 523840 }, + { name: 'Chanel', zID: 542567 }, + { name: 'Nikki', zID: 524596 }, + { name: 'Micky', zID: 523948 }, + { name: 'Jasmine', zID: 540938 }, ]; export default AddGroupButton; From 5268de7b5edc86710e60199b0f74afe30ee1a411 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Wed, 24 Apr 2024 21:27:59 +1000 Subject: [PATCH 04/92] removed close button styling --- .../src/components/sidebar/AddGroupButton.tsx | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/client/src/components/sidebar/AddGroupButton.tsx b/client/src/components/sidebar/AddGroupButton.tsx index 7c67eba03..9d556a742 100644 --- a/client/src/components/sidebar/AddGroupButton.tsx +++ b/client/src/components/sidebar/AddGroupButton.tsx @@ -1,7 +1,6 @@ import { - Close, + Close as CloseIcon, Add as AddIcon, - NotesOutlined, Edit as EditIcon, CheckCircle as CheckCircleIcon, RadioButtonUnchecked as RadioButtonUncheckedIcon, @@ -16,7 +15,6 @@ import { DialogContent, DialogTitle, IconButton, - InputAdornment, TextField, Tooltip, Typography, @@ -25,21 +23,18 @@ import { styled } from '@mui/system'; import React, { useState } from 'react'; const StyledDialogTitle = styled(DialogTitle)` - background-color: ${({ theme }) => theme.palette.background.paper}; // darkmode + background-color: ${({ theme }) => theme.palette.background.paper}; margin: 0; padding: 20px; + display: flex; + flex-direction: row; + justify-content: space-between; `; const StyledDialogActions = styled(DialogActions)` background-color: ${({ theme }) => theme.palette.background.paper}; // darkmode `; -const CloseButton = styled(IconButton)` - position: absolute; - right: 10px; - top: 10px; -`; - const StyledTypography = styled(Typography)` margin-top: 10px; margin-bottom: 10px; @@ -136,9 +131,9 @@ const AddGroupButton = () => { Create a Group - - - + + + @@ -160,6 +155,7 @@ const AddGroupButton = () => { + { fullWidth onChange={(e) => setGroupName(e.target.value)} /> - Date: Thu, 25 Apr 2024 20:10:32 +1000 Subject: [PATCH 05/92] clean up code and fixed darkmode appearance --- .../src/components/sidebar/AddGroupButton.tsx | 96 +++++++++---------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/client/src/components/sidebar/AddGroupButton.tsx b/client/src/components/sidebar/AddGroupButton.tsx index 9d556a742..f6f7191ae 100644 --- a/client/src/components/sidebar/AddGroupButton.tsx +++ b/client/src/components/sidebar/AddGroupButton.tsx @@ -24,47 +24,49 @@ import React, { useState } from 'react'; const StyledDialogTitle = styled(DialogTitle)` background-color: ${({ theme }) => theme.palette.background.paper}; - margin: 0; - padding: 20px; + padding: 40px; display: flex; flex-direction: row; justify-content: space-between; `; const StyledDialogActions = styled(DialogActions)` - background-color: ${({ theme }) => theme.palette.background.paper}; // darkmode -`; - -const StyledTypography = styled(Typography)` - margin-top: 10px; - margin-bottom: 10px; -`; - -const ShowModalButton = styled(IconButton)` - margin-right: 5px; + background-color: ${({ theme }) => theme.palette.background.paper}; + padding: 0px 60px 30px 0px; `; const StyledDialogContent = styled(DialogContent)` background-color: ${({ theme }) => theme.palette.background.paper}; - padding: 20px; - margin-top: 20px; + padding: 40px 60px; gap: 20px; display: flex; flex-direction: column; align-items: center; `; -const CircleOutline = styled('div')` +const Circle = ` width: 150px; height: 150px; border-radius: 999px; - border: 0.5px solid black; +`; + +const CircleOutline = styled('div')` + ${Circle} + border: 1px solid gray; cursor: pointer; + &:hover { + border: ${({ theme }) => (theme.palette.mode === 'light' ? '1px solid black' : '1px solid white;')}; + } +`; + +const CircleImage = styled('img')` + ${Circle} + object-fit: cover; `; -const EditCircleLabel = styled('label')` - background-color: white; - border: 0.5px solid black; +const EditIconCircleLabel = styled('label')` + background-color: ${({ theme }) => theme.palette.background.paper}; + border: 1px solid gray; border-radius: 999px; width: 35px; height: 35px; @@ -73,11 +75,18 @@ const EditCircleLabel = styled('label')` align-items: center; position: relative; top: -35px; + cursor: pointer; &:hover { - cursor: pointer; + border: ${({ theme }) => (theme.palette.mode === 'light' ? '1px solid black' : '1px solid white;')}; } `; +const StyledUploadImageContainer = styled('div')` + display: flex; + flex-direction: column; + align-items: flex-end; +`; + interface HiddenUploadFileProps { setSelectedFileImage: (file: null | File) => void; } @@ -102,7 +111,7 @@ const AddGroupButton = () => { const [isOpen, setIsOpen] = useState(false); const [groupName, setGroupName] = useState(''); const [selectedFriends, setSelectedFriends] = useState([]); - const [selectedFileImage, setSelectedFileImage] = useState(null); + const [selectedImage, setSelectedImage] = useState(null); const handleCreateGroup = () => { // TODO call API @@ -112,49 +121,38 @@ const AddGroupButton = () => { setIsOpen(false); setGroupName(''); setSelectedFriends([]); - setSelectedFileImage(null); - }; - - const handleDeleteSelectedMember = (zID: number) => { - setSelectedFriends(selectedFriends.filter((friend) => friend.zID !== zID)); + setSelectedImage(null); }; return ( <> - {/** + Button **/} - setIsOpen(true)}> + setIsOpen(true)}> - + - Create a Group - - - + Create a Group +
    + + + +
    -
    + - + - - -
    + + + { fullWidth onChange={(e) => setGroupName(e.target.value)} /> + { />
    - {/** FOOTER BUTTONS **/} - - -
    - - ); -}; - -/******* DUMMY FRIENDS DATABASE *******/ -interface FriendsType { - name: string; - zID: number; -} - -const friends: FriendsType[] = [ - { name: 'Shaam', zID: 532445 }, - { name: 'Ray', zID: 523495 }, - { name: 'hhlu', zID: 584290 }, - { name: 'Sohum', zID: 523840 }, - { name: 'Chanel', zID: 542567 }, - { name: 'Nikki', zID: 524596 }, - { name: 'Micky', zID: 523948 }, - { name: 'Jasmine', zID: 540938 }, -]; - -export default AddGroupButton; diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx new file mode 100644 index 000000000..138895a9f --- /dev/null +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -0,0 +1,53 @@ +import React, { useState } from 'react'; +import { Add as AddIcon } from '@mui/icons-material'; +import { Dialog, IconButton, Tooltip } from '@mui/material'; +import AddGroupDialogActions from './AddGroupDialogActions'; +import AddGroupDialogTitle from './AddGroupDialogTitle'; +import AddGroupDialogContent from './AddGroupDialogContent'; + + +export interface FriendType { + name: string; + zID: number; +} + +const AddGroupDialog = () => { + const [isOpen, setIsOpen] = useState(false); + const [groupName, setGroupName] = useState(''); + const [selectedFriends, setSelectedFriends] = useState([]); + const [groupImageURL, setGroupImageURL] = useState(''); + + const handleCreateGroup = () => { + // TODO call API + }; + + const handleClose = () => { + setIsOpen(false); + setGroupName(''); + setSelectedFriends([]); + setGroupImageURL(''); + }; + + return ( + <> + + setIsOpen(true)}> + + + + + + + + + + + ); +}; + +export default AddGroupDialog; diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx new file mode 100644 index 000000000..deb36dd72 --- /dev/null +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Button, DialogActions } from '@mui/material'; +import { styled } from '@mui/system'; + + +const StyledDialogActions = styled(DialogActions)` + background-color: ${({ theme }) => theme.palette.background.paper}; + padding: 0px 60px 30px 0px; +`; + +interface AddGroupDialogActionsProps { + handleClose: () => void; + handleCreateGroup: () => void; +} + +const AddGroupDialogActions: React.FC = ({ handleClose, handleCreateGroup }) => { + return ( + + + + + ); +}; + +export default AddGroupDialogActions; diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx new file mode 100644 index 000000000..86fdd6ebb --- /dev/null +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { CheckCircle as CheckCircleIcon, RadioButtonUnchecked as RadioButtonUncheckedIcon } from '@mui/icons-material'; +import { Autocomplete, Checkbox, Chip, DialogContent, TextField, Tooltip } from '@mui/material'; +import { styled } from '@mui/system'; +import EditImagePopOver from './EditImagePopOver'; +import { friends } from './dummyData'; +import { FriendType } from './AddGroupDialog'; + + +const StyledDialogContent = styled(DialogContent)` + background-color: ${({ theme }) => theme.palette.background.paper}; + padding: 40px 60px; + gap: 20px; + display: flex; + flex-direction: column; + align-items: center; +`; + +const Circle = ` + width: 150px; + height: 150px; + border-radius: 999px; +`; + +const CircleOutline = styled('div')` + ${Circle} + border: 1px solid gray; +`; + +const CircleImage = styled('img')` + ${Circle} + object-fit: cover; +`; + +const StyledUploadImageContainer = styled('div')` + display: flex; + flex-direction: column; + align-items: flex-end; +`; + +interface AddGroupDialoContentProps { + groupImageURL: string; + setGroupImageURL: (url: string) => void; + setGroupName: (groupName: string) => void; + setSelectedFriends: (friends: FriendType[]) => void; +} + +const AddGroupDialogContent: React.FC = ({ + groupImageURL, + setGroupImageURL, + setGroupName, + setSelectedFriends, +}) => { + return ( + + + + + + + setGroupName(e.target.value)} + /> + + setSelectedFriends(value)} + getOptionLabel={(option) => option.name} + renderOption={(props, option, { selected }) => ( +
  • + } + checkedIcon={} + style={{ marginRight: 8 }} + checked={selected} + /> + {option.name} +
  • + )} + renderTags={(tagValue, getTagProps) => { + return tagValue.map((option, index) => ( + + + + )); + }} + renderInput={(params) => } + /> +
    + ); +}; + +export default AddGroupDialogContent; diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogTitle.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogTitle.tsx new file mode 100644 index 000000000..7e4d8c44b --- /dev/null +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogTitle.tsx @@ -0,0 +1,33 @@ +import { Close as CloseIcon } from '@mui/icons-material'; +import { DialogTitle, IconButton, Typography } from '@mui/material'; +import { styled } from '@mui/system'; + + +const StyledDialogTitle = styled(DialogTitle)` + background-color: ${({ theme }) => theme.palette.background.paper}; + padding: 40px; + display: flex; + flex-direction: row; + justify-content: space-between; +`; + +interface AddGroupDialogTitleProps { + handleClose: () => void; +} + +const AddGroupDialogTitle: React.FC = ({ handleClose }) => { + return ( + <> + + Create a Group +
    + + + +
    +
    + + ); +}; + +export default AddGroupDialogTitle; diff --git a/client/src/components/sidebar/addGroupDialog/EditImagePopOver.tsx b/client/src/components/sidebar/addGroupDialog/EditImagePopOver.tsx new file mode 100644 index 000000000..52a776152 --- /dev/null +++ b/client/src/components/sidebar/addGroupDialog/EditImagePopOver.tsx @@ -0,0 +1,67 @@ +import { Edit as EditIcon } from '@mui/icons-material'; +import { IconButton, Popover, TextField } from '@mui/material'; +import { styled } from '@mui/system'; +import React from 'react'; + + +const EditIconCircle = styled('div')` + background-color: ${({ theme }) => theme.palette.background.paper}; + border: 1px solid gray; + border-radius: 999px; + width: 35px; + height: 35px; + display: flex; + justify-content: center; + align-items: center; + position: relative; + top: -35px; + cursor: pointer; + &:hover { + border: ${({ theme }) => (theme.palette.mode === 'light' ? '1px solid black' : '1px solid white;')}; + } +`; + +interface EditImagePopOverProps { + groupImageURL: string; + setGroupImageURL: (url: string) => void; +} + +const EditImagePopOver: React.FC = ({ groupImageURL, setGroupImageURL }) => { + const [anchorEl, setAnchorEl] = React.useState(null); + + return ( + +
    + setAnchorEl(e.currentTarget)}> + + + + setAnchorEl(null)} + anchorOrigin={{ + vertical: 'bottom', + horizontal: 'left', + }} + transformOrigin={{ + vertical: 'top', + horizontal: 'center', + }} + > +
    + setGroupImageURL(e.target.value)} + /> +
    +
    +
    +
    + ); +}; + +export default EditImagePopOver; diff --git a/client/src/components/sidebar/addGroupDialog/dummyData.tsx b/client/src/components/sidebar/addGroupDialog/dummyData.tsx new file mode 100644 index 000000000..f6bc8602c --- /dev/null +++ b/client/src/components/sidebar/addGroupDialog/dummyData.tsx @@ -0,0 +1,13 @@ +import { FriendType } from "./AddGroupDialog"; + + +export const friends: FriendType[] = [ + { name: 'Shaam', zID: 532445 }, + { name: 'Ray', zID: 523495 }, + { name: 'hhlu', zID: 584290 }, + { name: 'Sohum', zID: 523840 }, + { name: 'Chanel', zID: 542567 }, + { name: 'Nikki', zID: 524596 }, + { name: 'Micky', zID: 523948 }, + { name: 'Jasmine', zID: 540938 }, +]; From 575007f9c01ab2a7e2209cd6582c7d9d1191b24f Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Thu, 2 May 2024 10:59:41 +1000 Subject: [PATCH 12/92] removed inline styling cuz ray is a butt about it --- .../sidebar/addGroupDialog/EditImagePopOver.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/src/components/sidebar/addGroupDialog/EditImagePopOver.tsx b/client/src/components/sidebar/addGroupDialog/EditImagePopOver.tsx index 52a776152..068b831a5 100644 --- a/client/src/components/sidebar/addGroupDialog/EditImagePopOver.tsx +++ b/client/src/components/sidebar/addGroupDialog/EditImagePopOver.tsx @@ -3,7 +3,6 @@ import { IconButton, Popover, TextField } from '@mui/material'; import { styled } from '@mui/system'; import React from 'react'; - const EditIconCircle = styled('div')` background-color: ${({ theme }) => theme.palette.background.paper}; border: 1px solid gray; @@ -21,6 +20,10 @@ const EditIconCircle = styled('div')` } `; +const StyledPopoverContent = styled('div')` + width: 400px; +`; + interface EditImagePopOverProps { groupImageURL: string; setGroupImageURL: (url: string) => void; @@ -49,7 +52,7 @@ const EditImagePopOver: React.FC = ({ groupImageURL, setG horizontal: 'center', }} > -
    + = ({ groupImageURL, setG fullWidth onChange={(e) => setGroupImageURL(e.target.value)} /> -
    + From c08e1e98c7ea42670116b67fec3e7da1c1d02cd8 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Thu, 2 May 2024 11:24:06 +1000 Subject: [PATCH 13/92] added background colour to sidebar --- client/src/components/sidebar/Circle.tsx | 23 +++++++++++++++++++ .../src/components/sidebar/GroupsSidebar.tsx | 15 ++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 client/src/components/sidebar/Circle.tsx diff --git a/client/src/components/sidebar/Circle.tsx b/client/src/components/sidebar/Circle.tsx new file mode 100644 index 000000000..bab557959 --- /dev/null +++ b/client/src/components/sidebar/Circle.tsx @@ -0,0 +1,23 @@ +import styled from '@emotion/styled'; +import React from 'react'; + +interface CircleProps { + size: number; +} + +interface StyledCircleProps { + size: number +} + +const StyledCircle: React.FC = styled('div')(({ size }) => ({ + width: size, + height: size, + borderRadius: 999, + border: '1px grey solid', +})); + +const Circle: React.FC = ({ size }) => { + return ; +}; + +export default Circle; diff --git a/client/src/components/sidebar/GroupsSidebar.tsx b/client/src/components/sidebar/GroupsSidebar.tsx index c91cf4e29..c8efbb042 100644 --- a/client/src/components/sidebar/GroupsSidebar.tsx +++ b/client/src/components/sidebar/GroupsSidebar.tsx @@ -1,6 +1,5 @@ import styled from '@emotion/styled'; import { Tooltip } from '@mui/material'; -import zIndex from '@mui/material/styles/zIndex'; import React, { useState } from 'react'; import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd'; @@ -22,11 +21,11 @@ const getItemStyle = (isDragging: boolean, draggableStyle: any) => ({ ...draggableStyle, // styles we need to apply on draggables }); -const ListStyle = { - background: 'lightgrey', - width: 'fit-content', - padding: 8, -}; +const StyledContainer = styled('div')` + background: ${({ theme }) => theme.palette.primary.main}; + width: fit-content; + padding: 8px; +` /////////////// COPIED FROM ADDGROUPBUTTON /////////////// const Circle = ` @@ -66,7 +65,7 @@ const GroupsSidebar = () => { {(provided, snapshot) => ( -
    + {items.map((item, idx) => ( {(provided, snapshot) => ( @@ -89,7 +88,7 @@ const GroupsSidebar = () => { ))} {provided.placeholder} -
    + )}
    From 9d89faadd1c0a2ca6f4e71bc13214dc38a152b10 Mon Sep 17 00:00:00 2001 From: ray Date: Fri, 10 May 2024 11:10:27 +1000 Subject: [PATCH 14/92] oidc tests --- server/.eslintrc.js | 25 + server/.gitignore | 56 +- server/.prettierrc | 4 + server/Dockerfile | 48 +- server/README.md | 75 +- server/nest-cli.json | 8 + server/package.json | 90 +- server/pnpm-lock.yaml | 5543 ++++++++++++++--- server/prisma/schema.prisma | 84 + server/src/app.controller.spec.ts | 22 + server/src/app.controller.ts | 12 + server/src/app.module.ts | 10 + server/src/app.service.ts | 8 + server/src/main.ts | 8 + server/test/app.e2e-spec.ts | 24 + server/test/jest-e2e.json | 9 + server/tsconfig.build.json | 4 + server/tsconfig.json | 20 +- server_old/.gitignore | 4 + {server => server_old}/.npmrc | 0 server_old/README.md | 30 + {server => server_old}/autotimetabler.proto | 0 server_old/package.json | 37 + server_old/pnpm-lock.yaml | 1338 ++++ {server => server_old}/proto-gen.sh | 0 {server => server_old}/server.ts | 0 {server => server_old}/src/app.ts | 0 {server => server_old}/src/config.ts | 0 .../src/controllers/getAutotimetable.ts | 0 .../src/controllers/index.ts | 0 {server => server_old}/src/index.ts | 0 .../src/proto/autotimetabler_grpc_pb.d.ts | 0 .../src/proto/autotimetabler_grpc_pb.js | 0 .../src/proto/autotimetabler_pb.d.ts | 0 .../src/proto/autotimetabler_pb.js | 0 server_old/tsconfig.json | 7 + 36 files changed, 6604 insertions(+), 862 deletions(-) create mode 100644 server/.eslintrc.js create mode 100644 server/.prettierrc create mode 100644 server/nest-cli.json create mode 100644 server/prisma/schema.prisma create mode 100644 server/src/app.controller.spec.ts create mode 100644 server/src/app.controller.ts create mode 100644 server/src/app.module.ts create mode 100644 server/src/app.service.ts create mode 100644 server/src/main.ts create mode 100644 server/test/app.e2e-spec.ts create mode 100644 server/test/jest-e2e.json create mode 100644 server/tsconfig.build.json create mode 100644 server_old/.gitignore rename {server => server_old}/.npmrc (100%) create mode 100644 server_old/README.md rename {server => server_old}/autotimetabler.proto (100%) create mode 100644 server_old/package.json create mode 100644 server_old/pnpm-lock.yaml rename {server => server_old}/proto-gen.sh (100%) rename {server => server_old}/server.ts (100%) rename {server => server_old}/src/app.ts (100%) rename {server => server_old}/src/config.ts (100%) rename {server => server_old}/src/controllers/getAutotimetable.ts (100%) rename {server => server_old}/src/controllers/index.ts (100%) rename {server => server_old}/src/index.ts (100%) rename {server => server_old}/src/proto/autotimetabler_grpc_pb.d.ts (100%) rename {server => server_old}/src/proto/autotimetabler_grpc_pb.js (100%) rename {server => server_old}/src/proto/autotimetabler_pb.d.ts (100%) rename {server => server_old}/src/proto/autotimetabler_pb.js (100%) create mode 100644 server_old/tsconfig.json diff --git a/server/.eslintrc.js b/server/.eslintrc.js new file mode 100644 index 000000000..259de13c7 --- /dev/null +++ b/server/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/server/.gitignore b/server/.gitignore index 7aca60aa5..4b56acfbe 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,4 +1,56 @@ -data/ -dist/ +# compiled output +/dist +/node_modules +/build + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS .DS_Store +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# temp directory +.temp +.tmp + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json diff --git a/server/.prettierrc b/server/.prettierrc new file mode 100644 index 000000000..dcb72794f --- /dev/null +++ b/server/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/server/Dockerfile b/server/Dockerfile index 5ca9e208b..c873db6bd 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,26 +1,46 @@ -# Dependency versions should be pinned -FROM node:21.3.0-alpine as builder -RUN npm i -g pnpm -WORKDIR /server +# # Dependency versions should be pinned +# FROM node:21.0.0-alpine as builder +# RUN npm i -g pnpm +# WORKDIR /server -COPY package.json pnpm-lock.yaml ./ -RUN pnpm i --frozen-lockfile +# COPY package.json pnpm-lock.yaml ./ +# RUN pnpm i --frozen-lockfile -COPY . . -RUN pnpm run build +# COPY . . +# RUN pnpm run build + + +# FROM node:21.0.0-alpine +# RUN npm i -g pnpm +# WORKDIR /server +# ENV NODE_ENV production +# COPY package.json pnpm-lock.yaml ./ +# RUN pnpm install --production -FROM node:21.3.0-alpine +# # COPY --from=builder /server/dist . +# # COPY ./src/proto/*.js ./src/proto/ + +# EXPOSE 3001 + +# CMD ["pnpm", "run", "start:prod"] + +# Use an official Node.js image as the base image +FROM node:21.0.0-alpine RUN npm i -g pnpm + +# Set the working directory inside the container WORKDIR /server -ENV NODE_ENV production +# Copy package.json and pnpm-lock.yaml to the working directory COPY package.json pnpm-lock.yaml ./ -RUN pnpm install --production +RUN pnpm install --frozen-lockfile -COPY --from=builder /server/dist . -COPY ./src/proto/*.js ./src/proto/ +# Copy the rest of the application code +COPY . . +# Expose the port your application listens on EXPOSE 3001 -CMD ["npm", "run", "start:production"] +# Command to run your application using PNPM +CMD ["pnpm", "run", "start"] \ No newline at end of file diff --git a/server/README.md b/server/README.md index 3e628e895..f5aa86c5d 100644 --- a/server/README.md +++ b/server/README.md @@ -1,30 +1,73 @@ -# Notangles Server +

    + Nest Logo +

    -The Notangles server allows the client to communicate with the autotimetabling server. +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

    A progressive Node.js framework for building efficient and scalable server-side applications.

    +

    +NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + + Support us + +

    + + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. ## Installation -The server has been verified to work with: +```bash +$ pnpm install +``` + +## Running the app + +```bash +# development +$ pnpm run start + +# watch mode +$ pnpm run start:dev + +# production mode +$ pnpm run start:prod +``` -- npm v8.3.1 -- node v16.14.0 +## Test -In the root server directory `server`, run `npm install` to install all the dependencies. +```bash +# unit tests +$ pnpm run test -## Running +# e2e tests +$ pnpm run test:e2e -Run `npm start` to start the server locally. The server will be hosted at http://localhost:3001. +# test coverage +$ pnpm run test:cov +``` -## Tech Stack +## Support -The Notangles server uses: +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). -- [MongoDB](https://www.mongodb.com/) -- [TypeScript](https://www.typescriptlang.org/) -- [Express](https://expressjs.com/) +## Stay in touch -## API endpoints +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) -### `POST /auto` +## License -Returns a list of ints that correspond to class times for the inputted data +Nest is [MIT licensed](LICENSE). diff --git a/server/nest-cli.json b/server/nest-cli.json new file mode 100644 index 000000000..f9aa683b1 --- /dev/null +++ b/server/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/server/package.json b/server/package.json index b0e28d452..2617d65c6 100644 --- a/server/package.json +++ b/server/package.json @@ -1,37 +1,71 @@ { - "name": "notangles-server", - "version": "1.0.0", - "private": true, + "name": "server", + "version": "0.0.1", "description": "", - "main": "app.js", + "author": "", + "private": true, + "license": "UNLICENSED", "scripts": { - "start": "NODE_ENV=DEV ts-node server.ts", - "start:production": "NODE_ENV=PROD node server.js", - "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc", - "prettier-format": "prettier 'src/*.ts' 'src/controllers/*.ts' --write", - "proto:gen": "./src/proto-gen.sh" + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "test": "jest", + "test:watch": "jest --watch", + "test:cov": "jest --coverage", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:e2e": "jest --config ./test/jest-e2e.json" }, - "author": "", - "license": "ISC", "dependencies": { - "@sentry/node": "7.84.0", - "@sentry/tracing": "7.84.0", - "@grpc/grpc-js": "1.9.12", - "body-parser": "1.20.2", - "buffer-from": "1.1.2", - "express": "4.18.2", - "google-protobuf": "3.21.2", - "grpc_tools_node_protoc_ts": "5.3.3", - "grpc-tools": "1.12.4", - "minimist": "1.2.8", - "ts-protoc-gen": "0.15.0" + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@prisma/client": "5.13.0", + "reflect-metadata": "^0.2.0", + "rxjs": "^7.8.1" }, "devDependencies": { - "@types/express": "4.17.21", - "@types/node": "20.12.3", - "prettier": "3.1.0", - "ts-node": "10.9.1", - "typescript": "4.9.5" + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@nestjs/testing": "^10.0.0", + "@types/express": "^4.17.17", + "@types/jest": "^29.5.2", + "@types/node": "^20.3.1", + "@types/supertest": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.42.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.5.0", + "prettier": "^3.0.0", + "prisma": "5.13.0", + "source-map-support": "^0.5.21", + "supertest": "^6.3.3", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.3", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.1.3" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" } } diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index 22800ef2d..60bb2d46c 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -5,907 +5,3977 @@ settings: excludeLinksFromLockfile: false dependencies: - '@grpc/grpc-js': - specifier: 1.9.12 - version: 1.9.12 - '@sentry/node': - specifier: 7.84.0 - version: 7.84.0 - '@sentry/tracing': - specifier: 7.84.0 - version: 7.84.0 - body-parser: - specifier: 1.20.2 - version: 1.20.2 - buffer-from: - specifier: 1.1.2 - version: 1.1.2 - express: - specifier: 4.18.2 - version: 4.18.2 - google-protobuf: - specifier: 3.21.2 - version: 3.21.2 - grpc-tools: - specifier: 1.12.4 - version: 1.12.4 - grpc_tools_node_protoc_ts: - specifier: 5.3.3 - version: 5.3.3 - minimist: - specifier: 1.2.8 - version: 1.2.8 - ts-protoc-gen: - specifier: 0.15.0 - version: 0.15.0 + '@nestjs/common': + specifier: ^10.0.0 + version: 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': + specifier: ^10.0.0 + version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/platform-express': + specifier: ^10.0.0 + version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) + '@prisma/client': + specifier: 5.13.0 + version: 5.13.0(prisma@5.13.0) + reflect-metadata: + specifier: ^0.2.0 + version: 0.2.2 + rxjs: + specifier: ^7.8.1 + version: 7.8.1 devDependencies: + '@nestjs/cli': + specifier: ^10.0.0 + version: 10.3.2 + '@nestjs/schematics': + specifier: ^10.0.0 + version: 10.1.1(typescript@5.4.5) + '@nestjs/testing': + specifier: ^10.0.0 + version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8)(@nestjs/platform-express@10.3.8) '@types/express': - specifier: 4.17.21 + specifier: ^4.17.17 version: 4.17.21 + '@types/jest': + specifier: ^29.5.2 + version: 29.5.12 '@types/node': - specifier: 20.12.3 - version: 20.12.3 + specifier: ^20.3.1 + version: 20.12.10 + '@types/supertest': + specifier: ^6.0.0 + version: 6.0.2 + '@typescript-eslint/eslint-plugin': + specifier: ^6.0.0 + version: 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': + specifier: ^6.0.0 + version: 6.21.0(eslint@8.57.0)(typescript@5.4.5) + eslint: + specifier: ^8.42.0 + version: 8.57.0 + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.1.0(eslint@8.57.0) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5) + jest: + specifier: ^29.5.0 + version: 29.7.0(@types/node@20.12.10)(ts-node@10.9.2) prettier: - specifier: 3.1.0 - version: 3.1.0 + specifier: ^3.0.0 + version: 3.2.5 + prisma: + specifier: 5.13.0 + version: 5.13.0 + source-map-support: + specifier: ^0.5.21 + version: 0.5.21 + supertest: + specifier: ^6.3.3 + version: 6.3.4 + ts-jest: + specifier: ^29.1.0 + version: 29.1.2(@babel/core@7.24.5)(jest@29.7.0)(typescript@5.4.5) + ts-loader: + specifier: ^9.4.3 + version: 9.5.1(typescript@5.4.5)(webpack@5.91.0) ts-node: - specifier: 10.9.1 - version: 10.9.1(@types/node@20.12.3)(typescript@4.9.5) + specifier: ^10.9.1 + version: 10.9.2(@types/node@20.12.10)(typescript@5.4.5) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 typescript: - specifier: 4.9.5 - version: 4.9.5 + specifier: ^5.1.3 + version: 5.4.5 packages: - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} + /@ampproject/remapping@2.3.0: + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} dependencies: - '@jridgewell/trace-mapping': 0.3.9 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 dev: true - /@grpc/grpc-js@1.9.12: - resolution: {integrity: sha512-Um5MBuge32TS3lAKX02PGCnFM4xPT996yLgZNb5H03pn6NyJ4Iwn5YcPq6Jj9yxGRk7WOgaZFtVRH5iTdYBeUg==} - engines: {node: ^8.13.0 || >=10.10.0} + /@angular-devkit/core@17.1.2(chokidar@3.6.0): + resolution: {integrity: sha512-ku+/W/HMCBacSWFppenr9y6Lx8mDuTuQvn1IkTyBLiJOpWnzgVbx9kHDeaDchGa1PwLlJUBBrv27t3qgJOIDPw==} + engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^3.5.2 + peerDependenciesMeta: + chokidar: + optional: true dependencies: - '@grpc/proto-loader': 0.7.10 - '@types/node': 20.12.3 - dev: false + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + chokidar: 3.6.0 + jsonc-parser: 3.2.0 + picomatch: 3.0.1 + rxjs: 7.8.1 + source-map: 0.7.4 + dev: true - /@grpc/proto-loader@0.7.10: - resolution: {integrity: sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==} - engines: {node: '>=6'} + /@angular-devkit/schematics-cli@17.1.2(chokidar@3.6.0): + resolution: {integrity: sha512-bvXykYzSST05qFdlgIzUguNOb3z0hCa8HaTwtqdmQo9aFPf+P+/AC56I64t1iTchMjQtf3JrBQhYM25gUdcGbg==} + engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true dependencies: - lodash.camelcase: 4.3.0 - long: 5.2.3 - protobufjs: 7.2.5 - yargs: 17.7.2 - dev: false - - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} + '@angular-devkit/core': 17.1.2(chokidar@3.6.0) + '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) + ansi-colors: 4.1.3 + inquirer: 9.2.12 + symbol-observable: 4.0.0 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - chokidar dev: true - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + /@angular-devkit/schematics@17.1.2(chokidar@3.6.0): + resolution: {integrity: sha512-8S9RuM8olFN/gwN+mjbuF1CwHX61f0i59EGXz9tXLnKRUTjsRR+8vVMTAmX0dvVAT5fJTG/T69X+HX7FeumdqA==} + engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 17.1.2(chokidar@3.6.0) + jsonc-parser: 3.2.0 + magic-string: 0.30.5 + ora: 5.4.1 + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar dev: true - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + /@babel/code-frame@7.24.2: + resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + engines: {node: '>=6.9.0'} dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@babel/highlight': 7.24.5 + picocolors: 1.0.0 dev: true - /@mapbox/node-pre-gyp@1.0.11: - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true + /@babel/compat-data@7.24.4: + resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.24.5: + resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==} + engines: {node: '>=6.9.0'} dependencies: - detect-libc: 2.0.2 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.5.4 - tar: 6.2.0 + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) + '@babel/helpers': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 transitivePeerDependencies: - - encoding - supports-color - dev: false - - /@protobufjs/aspromise@1.1.2: - resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - dev: false + dev: true - /@protobufjs/base64@1.1.2: - resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - dev: false + /@babel/generator@7.24.5: + resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + dev: true - /@protobufjs/codegen@2.0.4: - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} - dev: false + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.24.4 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.23.0 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true - /@protobufjs/eventemitter@1.1.0: - resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} - dev: false + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true - /@protobufjs/fetch@1.1.0: - resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/inquire': 1.1.0 - dev: false - - /@protobufjs/float@1.0.2: - resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - dev: false + '@babel/template': 7.24.0 + '@babel/types': 7.24.5 + dev: true - /@protobufjs/inquire@1.1.0: - resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} - dev: false + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + dev: true - /@protobufjs/path@1.1.2: - resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - dev: false + /@babel/helper-module-imports@7.24.3: + resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + dev: true - /@protobufjs/pool@1.1.0: - resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - dev: false + /@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.24.3 + '@babel/helper-simple-access': 7.24.5 + '@babel/helper-split-export-declaration': 7.24.5 + '@babel/helper-validator-identifier': 7.24.5 + dev: true - /@protobufjs/utf8@1.1.0: - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - dev: false + /@babel/helper-plugin-utils@7.24.5: + resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==} + engines: {node: '>=6.9.0'} + dev: true - /@sentry-internal/tracing@7.84.0: - resolution: {integrity: sha512-y9bGYA0OM6PEREfd+nk4UURZy29tpIw+7vQwpxWfEVs2fqq0/5TBFX/tKFb8AKUI9lVM8v0bcF0bNSCnuPQZHQ==} - engines: {node: '>=8'} + /@babel/helper-simple-access@7.24.5: + resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} + engines: {node: '>=6.9.0'} dependencies: - '@sentry/core': 7.84.0 - '@sentry/types': 7.84.0 - '@sentry/utils': 7.84.0 - dev: false + '@babel/types': 7.24.5 + dev: true - /@sentry/core@7.84.0: - resolution: {integrity: sha512-tbuwunbBx2kSex15IHCqHDnrMfIlqPc6w/76fwkGqokz3oh9GSEGlLICwmBWL8AypWimUg13IDtFpD0TJTriWA==} - engines: {node: '>=8'} + /@babel/helper-split-export-declaration@7.24.5: + resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} + engines: {node: '>=6.9.0'} dependencies: - '@sentry/types': 7.84.0 - '@sentry/utils': 7.84.0 - dev: false + '@babel/types': 7.24.5 + dev: true - /@sentry/node@7.84.0: - resolution: {integrity: sha512-Xm3fIXT3TZOQi+6uQBavI8iOehD3PkY7v0y3hog0d4lQTH88vQK9BBsI+jZEq81Em+RG/u7vZNiFo6YMTnWF7Q==} - engines: {node: '>=8'} + /@babel/helper-string-parser@7.24.1: + resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.24.5: + resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers@7.24.5: + resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} + engines: {node: '>=6.9.0'} dependencies: - '@sentry-internal/tracing': 7.84.0 - '@sentry/core': 7.84.0 - '@sentry/types': 7.84.0 - '@sentry/utils': 7.84.0 - https-proxy-agent: 5.0.1 + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 transitivePeerDependencies: - supports-color - dev: false + dev: true - /@sentry/tracing@7.84.0: - resolution: {integrity: sha512-NhBX28vUmCu/5avyGKX6B4UTm4MTOfbdg9ZzCnS7hPuWDfEAUIVHZVryi2q8bqp2DNGJvS9qIq/TSf39JIpdJg==} - engines: {node: '>=8'} + /@babel/highlight@7.24.5: + resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} + engines: {node: '>=6.9.0'} dependencies: - '@sentry-internal/tracing': 7.84.0 - dev: false + '@babel/helper-validator-identifier': 7.24.5 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.0 + dev: true - /@sentry/types@7.84.0: - resolution: {integrity: sha512-VqGLIF3JOUrk7yIXjLXJvAORkZL1e3dDX0Q1okRehwyt/5CRE+mdUTeJZkBo9P9mBwgMyvtwklzOGGrzjb4eMA==} - engines: {node: '>=8'} - dev: false + /@babel/parser@7.24.5: + resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.24.5 + dev: true - /@sentry/utils@7.84.0: - resolution: {integrity: sha512-qdUVuxnRBvaf05AU+28R+xYtZmi/Ymf8os3Njq9g4XuA+QEkZLbzmIpRK5W9Ja7vUtjOeg29Xgg43A8znde9LQ==} - engines: {node: '>=8'} + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.5): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@sentry/types': 7.84.0 - dev: false + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: true - /@tsconfig/node10@1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.5): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/body-parser@1.19.3: - resolution: {integrity: sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==} + /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@types/connect': 3.4.36 - '@types/node': 20.12.3 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/connect@3.4.36: - resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.5): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@types/node': 20.12.3 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/express-serve-static-core@4.17.37: - resolution: {integrity: sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==} + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@types/node': 20.12.3 - '@types/qs': 6.9.8 - '@types/range-parser': 1.2.5 - '@types/send': 0.17.2 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.5): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@types/body-parser': 1.19.3 - '@types/express-serve-static-core': 4.17.37 - '@types/qs': 6.9.8 - '@types/serve-static': 1.15.3 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/http-errors@2.0.2: - resolution: {integrity: sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==} + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/mime@1.3.3: - resolution: {integrity: sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==} + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/mime@3.0.2: - resolution: {integrity: sha512-Wj+fqpTLtTbG7c0tH47dkahefpLKEbB+xAZuLq7b4/IDHPl/n6VoXcyUQ2bypFlbSwvCr0y+bD4euTTqTJsPxQ==} + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.5): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/node@20.12.3: - resolution: {integrity: sha512-sD+ia2ubTeWrOu+YMF+MTAB7E+O7qsMqAbMfW7DG3K1URwhZ5hN1pLlRVGbf4wDFzSfikL05M17EyorS86jShw==} + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.5): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - undici-types: 5.26.5 + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 + dev: true - /@types/qs@6.9.8: - resolution: {integrity: sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==} + /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5): + resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-plugin-utils': 7.24.5 dev: true - /@types/range-parser@1.2.5: - resolution: {integrity: sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==} + /@babel/template@7.24.0: + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 dev: true - /@types/send@0.17.2: - resolution: {integrity: sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==} + /@babel/traverse@7.24.5: + resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} + engines: {node: '>=6.9.0'} dependencies: - '@types/mime': 1.3.3 - '@types/node': 20.12.3 + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color dev: true - /@types/serve-static@1.15.3: - resolution: {integrity: sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==} + /@babel/types@7.24.5: + resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} + engines: {node: '>=6.9.0'} dependencies: - '@types/http-errors': 2.0.2 - '@types/mime': 3.0.2 - '@types/node': 20.12.3 + '@babel/helper-string-parser': 7.24.1 + '@babel/helper-validator-identifier': 7.24.5 + to-fast-properties: 2.0.0 dev: true - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: false + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} + /@colors/colors@1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true + optional: true + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: false + '@jridgewell/trace-mapping': 0.3.9 + dev: true - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 dev: true - /acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} - engines: {node: '>=0.4.0'} - hasBin: true + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: + ajv: 6.12.6 debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - dev: false + dev: true - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: false + /@eslint/js@8.57.0: + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} dependencies: - color-convert: 2.0.1 - dev: false + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true - /aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: false + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true - /are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} + /@humanwhocodes/object-schema@2.0.3: + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + dev: true + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - dev: false + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 dev: true - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: false + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: false + /@jest/console@29.7.0: + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + dev: true - /body-parser@1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + /@jest/core@29.7.0(ts-node@10.9.2): + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.12.10)(ts-node@10.9.2) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 transitivePeerDependencies: + - babel-plugin-macros - supports-color - dev: false + - ts-node + dev: true - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + /@jest/environment@29.7.0: + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + jest-mock: 29.7.0 + dev: true + + /@jest/expect-utils@29.7.0: + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 + dev: true + + /@jest/expect@29.7.0: + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 transitivePeerDependencies: - supports-color - dev: false + dev: true - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + /@jest/fake-timers@29.7.0: + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: false - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: false + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 20.12.10 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + dev: true - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: false + /@jest/globals@29.7.0: + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: true - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + /@jest/reporters@29.7.0: + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.2.1 - dev: false + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + '@types/node': 20.12.10 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.2.0 + transitivePeerDependencies: + - supports-color + dev: true - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jest/source-map@29.6.3: + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + callsites: 3.1.0 + graceful-fs: 4.2.11 + dev: true + + /@jest/test-result@29.7.0: + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + dev: true + + /@jest/test-sequencer@29.7.0: + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + dev: true + + /@jest/transform@29.7.0: + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.24.5 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.5 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/types@29.6.3: + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 20.12.10 + '@types/yargs': 17.0.32 + chalk: 4.1.2 + dev: true + + /@jridgewell/gen-mapping@0.3.5: + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@jridgewell/resolve-uri@3.1.2: + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.2.1: + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map@0.3.6: + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.25: + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@ljharb/through@2.3.13: + resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /@lukeed/csprng@1.1.0: + resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} + engines: {node: '>=8'} + + /@nestjs/cli@10.3.2: + resolution: {integrity: sha512-aWmD1GLluWrbuC4a1Iz/XBk5p74Uj6nIVZj6Ov03JbTfgtWqGFLtXuMetvzMiHxfrHehx/myt2iKAPRhKdZvTg==} + engines: {node: '>= 16.14'} + hasBin: true + peerDependencies: + '@swc/cli': ^0.1.62 || ^0.3.0 + '@swc/core': ^1.3.62 + peerDependenciesMeta: + '@swc/cli': + optional: true + '@swc/core': + optional: true + dependencies: + '@angular-devkit/core': 17.1.2(chokidar@3.6.0) + '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) + '@angular-devkit/schematics-cli': 17.1.2(chokidar@3.6.0) + '@nestjs/schematics': 10.1.1(chokidar@3.6.0)(typescript@5.3.3) + chalk: 4.1.2 + chokidar: 3.6.0 + cli-table3: 0.6.3 + commander: 4.1.1 + fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.90.1) + glob: 10.3.10 + inquirer: 8.2.6 + node-emoji: 1.11.0 + ora: 5.4.1 + rimraf: 4.4.1 + shelljs: 0.8.5 + source-map-support: 0.5.21 + tree-kill: 1.2.2 + tsconfig-paths: 4.2.0 + tsconfig-paths-webpack-plugin: 4.1.0 + typescript: 5.3.3 + webpack: 5.90.1 + webpack-node-externals: 3.0.0 + transitivePeerDependencies: + - esbuild + - uglify-js + - webpack-cli + dev: true + + /@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1): + resolution: {integrity: sha512-P+vPEIvqx2e+fonsYVlFXKvoChyJ8Tq+lfpqdVFqblovHbFr3kZ/nYX0cPs+XuW6bnRT8tz0SSR9XBGU43kJhw==} + peerDependencies: + class-transformer: '*' + class-validator: '*' + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + dependencies: + iterare: 1.2.1 + reflect-metadata: 0.2.2 + rxjs: 7.8.1 + tslib: 2.6.2 + uid: 2.0.2 + + /@nestjs/core@10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1): + resolution: {integrity: sha512-AxF4tpYLDNn5Wfb3C4bNaaHJ4pREH5FJrSisR2A5zkYpQFORFs0Tc36lOFPMwBTy8Iv2wUwWLUVc5ftBnxEv4w==} + requiresBuild: true + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/microservices': ^10.0.0 + '@nestjs/platform-express': ^10.0.0 + '@nestjs/websockets': ^10.0.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + '@nestjs/websockets': + optional: true + dependencies: + '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) + '@nuxtjs/opencollective': 0.3.2 + fast-safe-stringify: 2.1.1 + iterare: 1.2.1 + path-to-regexp: 3.2.0 + reflect-metadata: 0.2.2 + rxjs: 7.8.1 + tslib: 2.6.2 + uid: 2.0.2 + transitivePeerDependencies: + - encoding + + /@nestjs/platform-express@10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8): + resolution: {integrity: sha512-sifLoxgEJvAgbim1UuW6wyScMfkS9SVQRH+lN33N/9ZvZSjO6NSDLOe+wxqsnZkia+QrjFC0qy0ITRAsggfqbg==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + dependencies: + '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) + body-parser: 1.20.2 + cors: 2.8.5 + express: 4.19.2 + multer: 1.4.4-lts.1 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + + /@nestjs/schematics@10.1.1(chokidar@3.6.0)(typescript@5.3.3): + resolution: {integrity: sha512-o4lfCnEeIkfJhGBbLZxTuVWcGuqDCFwg5OrvpgRUBM7vI/vONvKKiB5riVNpO+JqXoH0I42NNeDb0m4V5RREig==} + peerDependencies: + typescript: '>=4.8.2' + dependencies: + '@angular-devkit/core': 17.1.2(chokidar@3.6.0) + '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) + comment-json: 4.2.3 + jsonc-parser: 3.2.1 + pluralize: 8.0.0 + typescript: 5.3.3 + transitivePeerDependencies: + - chokidar + dev: true + + /@nestjs/schematics@10.1.1(typescript@5.4.5): + resolution: {integrity: sha512-o4lfCnEeIkfJhGBbLZxTuVWcGuqDCFwg5OrvpgRUBM7vI/vONvKKiB5riVNpO+JqXoH0I42NNeDb0m4V5RREig==} + peerDependencies: + typescript: '>=4.8.2' + dependencies: + '@angular-devkit/core': 17.1.2(chokidar@3.6.0) + '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) + comment-json: 4.2.3 + jsonc-parser: 3.2.1 + pluralize: 8.0.0 + typescript: 5.4.5 + transitivePeerDependencies: + - chokidar + dev: true + + /@nestjs/testing@10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8)(@nestjs/platform-express@10.3.8): + resolution: {integrity: sha512-hpX9das2TdFTKQ4/2ojhjI6YgXtCfXRKui3A4Qaj54VVzc5+mtK502Jj18Vzji98o9MVS6skmYu+S/UvW3U6Fw==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + '@nestjs/microservices': ^10.0.0 + '@nestjs/platform-express': ^10.0.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + dependencies: + '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) + tslib: 2.6.2 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + dev: true + + /@nuxtjs/opencollective@0.3.2: + resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + consola: 2.15.3 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + + /@pkgr/core@0.1.1: + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dev: true + + /@prisma/client@5.13.0(prisma@5.13.0): + resolution: {integrity: sha512-uYdfpPncbZ/syJyiYBwGZS8Gt1PTNoErNYMuqHDa2r30rNSFtgTA/LXsSk55R7pdRTMi5pHkeP9B14K6nHmwkg==} + engines: {node: '>=16.13'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dependencies: + prisma: 5.13.0 + dev: false + + /@prisma/debug@5.13.0: + resolution: {integrity: sha512-699iqlEvzyCj9ETrXhs8o8wQc/eVW+FigSsHpiskSFydhjVuwTJEfj/nIYqTaWFYuxiWQRfm3r01meuW97SZaQ==} + + /@prisma/engines-version@5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b: + resolution: {integrity: sha512-AyUuhahTINGn8auyqYdmxsN+qn0mw3eg+uhkp8zwknXYIqoT3bChG4RqNY/nfDkPvzWAPBa9mrDyBeOnWSgO6A==} + + /@prisma/engines@5.13.0: + resolution: {integrity: sha512-hIFLm4H1boj6CBZx55P4xKby9jgDTeDG0Jj3iXtwaaHmlD5JmiDkZhh8+DYWkTGchu+rRF36AVROLnk0oaqhHw==} + requiresBuild: true + dependencies: + '@prisma/debug': 5.13.0 + '@prisma/engines-version': 5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b + '@prisma/fetch-engine': 5.13.0 + '@prisma/get-platform': 5.13.0 + + /@prisma/fetch-engine@5.13.0: + resolution: {integrity: sha512-Yh4W+t6YKyqgcSEB3odBXt7QyVSm0OQlBSldQF2SNXtmOgMX8D7PF/fvH6E6qBCpjB/yeJLy/FfwfFijoHI6sA==} + dependencies: + '@prisma/debug': 5.13.0 + '@prisma/engines-version': 5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b + '@prisma/get-platform': 5.13.0 + + /@prisma/get-platform@5.13.0: + resolution: {integrity: sha512-B/WrQwYTzwr7qCLifQzYOmQhZcFmIFhR81xC45gweInSUn2hTEbfKUPd2keAog+y5WI5xLAFNJ3wkXplvSVkSw==} + dependencies: + '@prisma/debug': 5.13.0 + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sinonjs/commons@3.0.1: + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers@10.3.0: + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + dependencies: + '@sinonjs/commons': 3.0.1 + dev: true + + /@tsconfig/node10@1.0.11: + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + dev: true + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.5 + dev: true + + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + dependencies: + '@babel/types': 7.24.5 + dev: true + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 + dev: true + + /@types/babel__traverse@7.20.5: + resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + dependencies: + '@babel/types': 7.24.5 + dev: true + + /@types/body-parser@1.19.5: + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + dependencies: + '@types/connect': 3.4.38 + '@types/node': 20.12.10 + dev: true + + /@types/connect@3.4.38: + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + dependencies: + '@types/node': 20.12.10 + dev: true + + /@types/cookiejar@2.1.5: + resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} + dev: true + + /@types/eslint-scope@3.7.7: + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + dependencies: + '@types/eslint': 8.56.10 + '@types/estree': 1.0.5 + dev: true + + /@types/eslint@8.56.10: + resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/express-serve-static-core@4.19.0: + resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} + dependencies: + '@types/node': 20.12.10 + '@types/qs': 6.9.15 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + dev: true + + /@types/express@4.17.21: + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.0 + '@types/qs': 6.9.15 + '@types/serve-static': 1.15.7 + dev: true + + /@types/graceful-fs@4.1.9: + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + dependencies: + '@types/node': 20.12.10 + dev: true + + /@types/http-errors@2.0.4: + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + dev: true + + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + + /@types/istanbul-lib-report@3.0.3: + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + dev: true + + /@types/istanbul-reports@3.0.4: + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + dependencies: + '@types/istanbul-lib-report': 3.0.3 + dev: true + + /@types/jest@29.5.12: + resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/methods@1.1.4: + resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} + dev: true + + /@types/mime@1.3.5: + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + dev: true + + /@types/node@20.12.10: + resolution: {integrity: sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/qs@6.9.15: + resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} + dev: true + + /@types/range-parser@1.2.7: + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + dev: true + + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: true + + /@types/send@0.17.4: + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + dependencies: + '@types/mime': 1.3.5 + '@types/node': 20.12.10 + dev: true + + /@types/serve-static@1.15.7: + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 20.12.10 + '@types/send': 0.17.4 + dev: true + + /@types/stack-utils@2.0.3: + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + dev: true + + /@types/superagent@8.1.7: + resolution: {integrity: sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==} + dependencies: + '@types/cookiejar': 2.1.5 + '@types/methods': 1.1.4 + '@types/node': 20.12.10 + dev: true + + /@types/supertest@6.0.2: + resolution: {integrity: sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==} + dependencies: + '@types/methods': 1.1.4 + '@types/superagent': 8.1.7 + dev: true + + /@types/yargs-parser@21.0.3: + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + dev: true + + /@types/yargs@17.0.32: + resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + dependencies: + '@types/yargs-parser': 21.0.3 + dev: true + + /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + eslint: 8.57.0 + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.21.0: + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + dev: true + + /@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + debug: 4.3.4 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.21.0: + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.21.0(typescript@5.4.5): + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.21.0: + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@webassemblyjs/ast@1.12.1: + resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + dev: true + + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + dev: true + + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + dev: true + + /@webassemblyjs/helper-buffer@1.12.1: + resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} + dev: true + + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + dev: true + + /@webassemblyjs/helper-wasm-section@1.12.1: + resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.12.1 + dev: true + + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: true + + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + dependencies: + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + dev: true + + /@webassemblyjs/wasm-edit@1.12.1: + resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-opt': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + '@webassemblyjs/wast-printer': 1.12.1 + dev: true + + /@webassemblyjs/wasm-gen@1.12.1: + resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: true + + /@webassemblyjs/wasm-opt@1.12.1: + resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + dev: true + + /@webassemblyjs/wasm-parser@1.12.1: + resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: true + + /@webassemblyjs/wast-printer@1.12.1: + resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@xtuc/long': 4.2.2 + dev: true + + /@xtuc/ieee754@1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: true + + /@xtuc/long@4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: true + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + /acorn-import-assertions@1.9.0(acorn@8.11.3): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.11.3 + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.3): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.3 + dev: true + + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv-formats@2.1.1(ajv@8.12.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + dev: true + + /ajv-keywords@3.5.2(ajv@6.12.6): + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /append-field@1.0.0: + resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + /array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + + /babel-jest@29.7.0(@babel/core@7.24.5): + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.24.5 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.24.5) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.24.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/template': 7.24.0 + '@babel/types': 7.24.5 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.5 + dev: true + + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.5): + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5) + dev: true + + /babel-preset-jest@29.6.3(@babel/core@7.24.5): + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + dev: true + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001616 + electron-to-chromium: 1.4.757 + node-releases: 2.0.14 + update-browserslist-db: 1.0.15(browserslist@4.23.0) + dev: true + + /bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + dependencies: + fast-json-stable-stringify: 2.1.0 + dev: true + + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + dependencies: + streamsearch: 1.1.0 + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite@1.0.30001616: + resolution: {integrity: sha512-RHVYKov7IcdNjVHJFNY/78RdG4oGVjbayxv8u5IO74Wv7Hlq4PnJE6mo/OjFijjVFNy5ijnCt6H3IIo4t+wfEw==} + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: true + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /chrome-trace-event@1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: true + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: true + + /cjs-module-lexer@1.3.1: + resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} + dev: true + + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + dev: true + + /cli-table3@0.6.3: + resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + dev: true + + /cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: true + + /cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + + /co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: true + + /comment-json@4.2.3: + resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} + engines: {node: '>= 6'} + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + has-own-prop: 2.0.0 + repeat-string: 1.6.1 + dev: true + + /component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + + /consola@2.15.3: + resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + /cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + + /cookiejar@2.1.4: + resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} + dev: true + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + /cosmiconfig@8.3.6(typescript@5.3.3): + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + typescript: 5.3.3 + dev: true + + /create-jest@29.7.0(@types/node@20.12.10)(ts-node@10.9.2): + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.12.10)(ts-node@10.9.2) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + /detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: true + + /dezalgo@1.0.4: + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + dev: true + + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + /electron-to-chromium@1.4.757: + resolution: {integrity: sha512-jftDaCknYSSt/+KKeXzH3LX5E2CvRLm75P3Hj+J/dv3CL0qUYcOt13d5FN1NiL5IJbbhzHrb3BomeG2tkSlZmw==} + dev: true + + /emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + /enhanced-resolve@5.16.0: + resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + /es-module-lexer@1.5.2: + resolution: {integrity: sha512-l60ETUTmLqbVbVHv1J4/qj+M8nq7AwMzEcg3kmJDt9dCNrTk+yHcYFf/Kw75pMDwd9mPcIGCG5LcS20SxYRzFA==} + dev: true + + /escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + dev: true + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - dev: false + dev: true + + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: true + + /eslint-config-prettier@9.1.0(eslint@8.57.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5): + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.57.0 + eslint-config-prettier: 9.1.0(eslint@8.57.0) + prettier: 3.2.5 + prettier-linter-helpers: 1.0.0 + synckit: 0.8.8 + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: true + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + dev: true + + /express@4.19.2: + resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.2 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.6.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + /fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + dependencies: + reusify: 1.0.4 + dev: true + + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: true + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /figures@5.0.0: + resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} + engines: {node: '>=14'} + dependencies: + escape-string-regexp: 5.0.0 + is-unicode-supported: 1.3.0 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + dev: true + + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: true + + /fork-ts-checker-webpack-plugin@9.0.2(typescript@5.3.3)(webpack@5.90.1): + resolution: {integrity: sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==} + engines: {node: '>=12.13.0', yarn: '>=1.0.0'} + peerDependencies: + typescript: '>3.6.0' + webpack: ^5.11.0 + dependencies: + '@babel/code-frame': 7.24.2 + chalk: 4.1.2 + chokidar: 3.6.0 + cosmiconfig: 8.3.6(typescript@5.3.3) + deepmerge: 4.3.1 + fs-extra: 10.1.0 + memfs: 3.5.3 + minimatch: 3.1.2 + node-abort-controller: 3.1.1 + schema-utils: 3.3.0 + semver: 7.6.0 + tapable: 2.2.1 + typescript: 5.3.3 + webpack: 5.90.1 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /formidable@2.1.2: + resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==} + dependencies: + dezalgo: 1.0.4 + hexoid: 1.0.0 + once: 1.4.0 + qs: 6.12.1 + dev: true - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fs-monkey@1.0.6: + resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + /get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: true + + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.4 + minipass: 7.1.0 + path-scurry: 1.10.2 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@9.3.5: + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + fs.realpath: 1.0.0 + minimatch: 8.0.4 + minipass: 4.2.8 + path-scurry: 1.10.2 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + /has-own-prop@2.0.0: + resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /hexoid@1.0.0: + resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==} + engines: {node: '>=8'} + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /inquirer@8.2.6: + resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.1 string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false + through: 2.3.8 + wrap-ansi: 6.2.0 + dev: true - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + /inquirer@9.2.12: + resolution: {integrity: sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==} + engines: {node: '>=14.18.0'} dependencies: - color-name: 1.1.4 - dev: false + '@ljharb/through': 2.3.13 + ansi-escapes: 4.3.2 + chalk: 5.3.0 + cli-cursor: 3.1.0 + cli-width: 4.1.0 + external-editor: 3.1.0 + figures: 5.0.0 + lodash: 4.17.21 + mute-stream: 1.0.0 + ora: 5.4.1 + run-async: 3.0.0 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: true - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false + /interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + dev: true - /color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: false + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: false + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true - /console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: false + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.3.0 + dev: true - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: - safe-buffer: 5.2.1 - dev: false + hasown: 2.0.2 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.24.5 + '@babel/parser': 7.24.5 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-instrument@6.0.2: + resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} + engines: {node: '>=10'} + dependencies: + '@babel/core': 7.24.5 + '@babel/parser': 7.24.5 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - dev: false + /iterare@1.2.1: + resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==} + engines: {node: '>=6'} - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: false + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - dev: false + /jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + dev: true - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + /jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color dev: true - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + /jest-cli@29.7.0(@types/node@20.12.10)(ts-node@10.9.2): + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true peerDependencies: - supports-color: '*' + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: - supports-color: + node-notifier: optional: true dependencies: - ms: 2.0.0 - dev: false + '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@20.12.10)(ts-node@10.9.2) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@20.12.10)(ts-node@10.9.2) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} + /jest-config@29.7.0(@types/node@20.12.10)(ts-node@10.9.2): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: - supports-color: '*' + '@types/node': '*' + ts-node: '>=9.0.0' peerDependenciesMeta: - supports-color: + '@types/node': + optional: true + ts-node: optional: true dependencies: - ms: 2.1.2 - dev: false + '@babel/core': 7.24.5 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + babel-jest: 29.7.0(@babel/core@7.24.5) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + ts-node: 10.9.2(@types/node@20.12.10)(typescript@5.4.5) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true - /delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: false + /jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: false + /jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + detect-newline: 3.1.0 + dev: true - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: false + /jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + dev: true - /detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - dev: false + /jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + jest-mock: 29.7.0 + jest-util: 29.7.0 + dev: true - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} + /jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: false + /jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 20.12.10 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + dev: true - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false + /jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: false + /jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: false + /jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/code-frame': 7.24.2 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + dev: true - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: false + /jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + jest-util: 29.7.0 + dev: true - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: false + /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 29.7.0 + dev: true - /express@4.18.2: - resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} - engines: {node: '>= 0.10.0'} + /jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.1 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.5.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 transitivePeerDependencies: - supports-color - dev: false + dev: true - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} + /jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.8 + resolve.exports: 2.0.2 + slash: 3.0.0 + dev: true + + /jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 transitivePeerDependencies: - supports-color - dev: false - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: false - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: false + dev: true - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} + /jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - minipass: 3.3.6 - dev: false - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: false - - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: false + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + chalk: 4.1.2 + cjs-module-lexer: 1.3.1 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true - /gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} + /jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: false + '@babel/core': 7.24.5 + '@babel/generator': 7.24.5 + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) + '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) + '@babel/types': 7.24.5 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + dev: true - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: false + /jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + dev: true - /get-intrinsic@1.2.1: - resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + /jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - function-bind: 1.1.1 - has: 1.0.4 - has-proto: 1.0.1 - has-symbols: 1.0.3 - dev: false + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + dev: true - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + /jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: false + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + dev: true - /google-protobuf@3.15.8: - resolution: {integrity: sha512-2jtfdqTaSxk0cuBJBtTTWsot4WtR9RVr2rXg7x7OoqiuOKopPrwXpM1G4dXIkLcUNRh3RKzz76C8IOkksZSeOw==} - dev: false + /jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 20.12.10 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true - /google-protobuf@3.21.2: - resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==} - dev: false + /jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 20.12.10 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true - /grpc-tools@1.12.4: - resolution: {integrity: sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==} + /jest@29.7.0(@types/node@20.12.10)(ts-node@10.9.2): + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true - requiresBuild: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true dependencies: - '@mapbox/node-pre-gyp': 1.0.11 + '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@20.12.10)(ts-node@10.9.2) transitivePeerDependencies: - - encoding + - '@types/node' + - babel-plugin-macros - supports-color - dev: false + - ts-node + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true - /grpc_tools_node_protoc_ts@5.3.3: - resolution: {integrity: sha512-M/YrklvVXMtuuj9kb42PxeouZhs7Ul+R4e/31XwrankUcKL8cQQP50Q9q+KEHGyHQaPt6VtKKsxMgLaKbCxeww==} + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true dependencies: - google-protobuf: 3.15.8 - handlebars: 4.7.7 - dev: false + argparse: 1.0.10 + esprima: 4.0.1 + dev: true - /handlebars@4.7.7: - resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} - engines: {node: '>=0.4.7'} + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.4 - dev: false + argparse: 2.0.1 + dev: true - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: false + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: false + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + + /jsonc-parser@3.2.1: + resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true - /has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: false + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true - /has@1.0.4: - resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} - engines: {node: '>= 0.4.0'} - dev: false + /leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: false + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} + /loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} dependencies: - safer-buffer: 2.1.2 - dev: false + p-locate: 4.1.0 + dev: true - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: false + p-locate: 5.0.0 + dev: true - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false + /lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + dev: true - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: false + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true - /lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - dev: false + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true - /long@5.2.3: - resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} - dev: false + /lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} dependencies: yallist: 4.0.0 - dev: false + dev: true - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} dependencies: - semver: 6.3.1 - dev: false + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.6.0 + dev: true /make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: true + /makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + /media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - dev: false + + /memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + dependencies: + fs-monkey: 1.0.6 + dev: true /merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: false + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - dev: false + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: false /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 - dev: false /mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} hasBin: true - dev: false + + /mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + dev: true + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: false + dev: true - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: false + /minimatch@8.0.4: + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} dependencies: - yallist: 4.0.0 - dev: false + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + /minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} engines: {node: '>=8'} - dev: false + dev: true - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - dev: false + /minipass@7.1.0: + resolution: {integrity: sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true - dev: false + dependencies: + minimist: 1.2.8 /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: false /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: false + dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false + + /multer@1.4.4-lts.1: + resolution: {integrity: sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==} + engines: {node: '>= 6.0.0'} + dependencies: + append-field: 1.0.0 + busboy: 1.6.0 + concat-stream: 1.6.2 + mkdirp: 0.5.6 + object-assign: 4.1.1 + type-is: 1.6.18 + xtend: 4.0.2 + + /mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: true + + /mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true /negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} - dev: false /neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: false + dev: true + + /node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + dev: true + + /node-emoji@1.11.0: + resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + dependencies: + lodash: 4.17.21 + dev: true /node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} @@ -917,85 +3987,253 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: false - /nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - abbrev: 1.1.1 - dev: false + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true - /npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: false + path-key: 3.1.1 + dev: true /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - dev: false - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: false + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} /on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} dependencies: ee-first: 1.1.1 - dev: false /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: - wrappy: 1.0.2 - dev: false + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + dev: true + + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.24.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-scurry@1.10.2: + resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.2.2 + minipass: 7.1.0 + dev: true + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + + /path-to-regexp@3.2.0: + resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==} + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /picomatch@3.0.1: + resolution: {integrity: sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==} + engines: {node: '>=10'} + dev: true + + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: true + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: false + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: false + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: false + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true - /prettier@3.1.0: - resolution: {integrity: sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==} + /prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} engines: {node: '>=14'} hasBin: true dev: true - /protobufjs@7.2.5: - resolution: {integrity: sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==} - engines: {node: '>=12.0.0'} + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + dev: true + + /prisma@5.13.0: + resolution: {integrity: sha512-kGtcJaElNRAdAGsCNykFSZ7dBKpL14Cbs+VaQ8cECxQlRPDjBlMHNFYeYt0SKovAVy2Y65JXQwB3A5+zIQwnTg==} + engines: {node: '>=16.13'} + hasBin: true requiresBuild: true dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/node': 20.12.3 - long: 5.2.3 - dev: false + '@prisma/engines': 5.13.0 + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} @@ -1003,29 +4241,42 @@ packages: dependencies: forwarded: 0.2.0 ipaddr.js: 1.9.1 - dev: false + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + dev: true /qs@6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} dependencies: - side-channel: 1.0.4 - dev: false + side-channel: 1.0.6 + + /qs@6.12.1: + resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.6 + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true /range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - dev: false - - /raw-body@2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: false /raw-body@2.5.2: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} @@ -1035,7 +4286,21 @@ packages: http-errors: 2.0.0 iconv-lite: 0.4.24 unpipe: 1.0.0 - dev: false + + /react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + dev: true + + /readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} @@ -1044,40 +4309,150 @@ packages: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: false + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + dependencies: + resolve: 1.22.8 + dev: true + + /reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: true /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - dev: false + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: glob: 7.2.3 - dev: false + dev: true + + /rimraf@4.4.1: + resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} + engines: {node: '>=14'} + hasBin: true + dependencies: + glob: 9.3.5 + dev: true + + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: true + + /run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + dependencies: + tslib: 2.6.2 + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: false + + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: true /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - dev: false + dev: true - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + /semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} engines: {node: '>=10'} hasBin: true dependencies: lru-cache: 6.0.0 - dev: false + dev: true /send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} @@ -1098,95 +4473,445 @@ packages: statuses: 2.0.1 transitivePeerDependencies: - supports-color - dev: false - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} + /serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + dependencies: + randombytes: 2.1.0 + dev: true + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + dev: true + + /side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + /streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + /string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /superagent@8.1.2: + resolution: {integrity: sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==} + engines: {node: '>=6.4.0 <13 || >=14'} + deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net + dependencies: + component-emitter: 1.3.1 + 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.12.1 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + dev: true + + /supertest@6.3.4: + resolution: {integrity: sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==} + engines: {node: '>=6.4.0'} dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 + methods: 1.1.2 + superagent: 8.1.2 transitivePeerDependencies: - supports-color - dev: false + dev: true - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: false + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - object-inspect: 1.12.3 - dev: false + has-flag: 4.0.0 + dev: true - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: false + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: false + /symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + dev: true - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: false + /synckit@0.8.8: + resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.6.2 + dev: true - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /terser-webpack-plugin@5.3.10(webpack@5.90.1): + resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: false + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.31.0 + webpack: 5.90.1 + dev: true - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + /terser-webpack-plugin@5.3.10(webpack@5.91.0): + resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true dependencies: - safe-buffer: 5.2.1 - dev: false + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.31.0 + webpack: 5.91.0 + dev: true - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + /terser@5.31.0: + resolution: {integrity: sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.11.3 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} dependencies: - ansi-regex: 5.0.1 - dev: false + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true - /tar@6.2.0: - resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} - engines: {node: '>=10'} + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: false + os-tmpdir: 1.0.2 + dev: true + + /tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - dev: false /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: false - /ts-node@10.9.1(@types/node@20.12.3)(typescript@4.9.5): - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + /tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + + /ts-api-utils@1.3.0(typescript@5.4.5): + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.4.5 + dev: true + + /ts-jest@29.1.2(@babel/core@7.24.5)(jest@29.7.0)(typescript@5.4.5): + resolution: {integrity: sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==} + engines: {node: ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + dependencies: + '@babel/core': 7.24.5 + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0(@types/node@20.12.10)(ts-node@10.9.2) + jest-util: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.6.0 + typescript: 5.4.5 + yargs-parser: 21.1.1 + dev: true + + /ts-loader@9.5.1(typescript@5.4.5)(webpack@5.91.0): + resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==} + engines: {node: '>=12.0.0'} + peerDependencies: + typescript: '*' + webpack: ^5.0.0 + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.16.0 + micromatch: 4.0.5 + semver: 7.6.0 + source-map: 0.7.4 + typescript: 5.4.5 + webpack: 5.91.0 + dev: true + + /ts-node@10.9.2(@types/node@20.12.10)(typescript@5.4.5): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: '@swc/core': '>=1.2.50' @@ -1200,28 +4925,64 @@ packages: optional: true dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 + '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.12.3 - acorn: 8.10.0 - acorn-walk: 8.2.0 + '@types/node': 20.12.10 + acorn: 8.11.3 + acorn-walk: 8.3.2 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 4.9.5 + typescript: 5.4.5 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 dev: true - /ts-protoc-gen@0.15.0: - resolution: {integrity: sha512-TycnzEyrdVDlATJ3bWFTtra3SCiEP0W0vySXReAuEygXCUr1j2uaVyL0DhzjwuUdQoW5oXPwk6oZWeA0955V+g==} - hasBin: true + /tsconfig-paths-webpack-plugin@4.1.0: + resolution: {integrity: sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==} + engines: {node: '>=10.13.0'} dependencies: - google-protobuf: 3.21.2 - dev: false + chalk: 4.1.2 + enhanced-resolve: 5.16.0 + tsconfig-paths: 4.2.0 + dev: true + + /tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} @@ -1229,68 +4990,222 @@ packages: dependencies: media-typer: 0.3.0 mime-types: 2.1.35 - dev: false - /typescript@4.9.5: - resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} - engines: {node: '>=4.2.0'} + /typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} hasBin: true dev: true - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} + /typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} hasBin: true - requiresBuild: true - dev: false - optional: true + dev: true + + /uid@2.0.2: + resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} + engines: {node: '>=8'} + dependencies: + '@lukeed/csprng': 1.1.0 /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true /unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - dev: false + + /update-browserslist-db@1.0.15(browserslist@4.23.0): + resolution: {integrity: sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.23.0 + escalade: 3.1.2 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false /utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - dev: false /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true + /v8-to-istanbul@9.2.0: + resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + dev: true + /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - dev: false + + /walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + + /watchpack@2.4.1: + resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: true + + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: false + + /webpack-node-externals@3.0.0: + resolution: {integrity: sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==} + engines: {node: '>=6'} + dev: true + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: true + + /webpack@5.90.1: + resolution: {integrity: sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.11.3 + acorn-import-assertions: 1.9.0(acorn@8.11.3) + browserslist: 4.23.0 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.16.0 + es-module-lexer: 1.5.2 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(webpack@5.90.1) + watchpack: 2.4.1 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /webpack@5.91.0: + resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.11.3 + acorn-import-assertions: 1.9.0(acorn@8.11.3) + browserslist: 4.23.0 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.16.0 + es-module-lexer: 1.5.2 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(webpack@5.91.0) + watchpack: 2.4.1 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: false - /wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true dependencies: - string-width: 4.2.3 - dev: false + isexe: 2.0.0 + dev: true - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: false + /word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} @@ -1299,40 +5214,70 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: false + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: false + dev: true + + /write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + + /xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - dev: false + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: false + dev: true /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - dev: false + dev: true /yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} dependencies: cliui: 8.0.1 - escalade: 3.1.1 + escalade: 3.1.2 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: false + dev: true /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma new file mode 100644 index 000000000..89fc4d291 --- /dev/null +++ b/server/prisma/schema.prisma @@ -0,0 +1,84 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +generator client { + provider = "prisma-client-js" + // output = "../node_modules/.prisma/client" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model User { + userId String @id // same as zid + createdAt DateTime @default(now()) + lastLogin DateTime? @default(now()) + firstname String? + lastname String? + email String + profileURL String? + timetable Timetable[] + settings Settings? + friends User[] @relation("UserFriends") + friendRequests User[] @relation("UserFriends") +} + +model Event { + id String @id + name String + location String? + description String? + colour String @default("#1F7E8C") + + // Event Time + day String + start DateTime + end DateTime + timetable Timetable? @relation(fields: [timetableId], references: [id]) + timetableId String? +} + +model Class { + id String @unique + classType String // e.g. Lecture, Tutorial, Laboratory, etc. Not putting into enum because there are other whacky classTypes + courseName String? + Timetable Timetable? @relation(fields: [timetableId], references: [id], onDelete: Cascade) + timetableId String? +} + +model Timetable { + id String @id @unique + name String + selectedCourses String[] + selectedClasses Class[] + createdEvents Event[] + user User @relation(fields: [userId], references: [userId], onDelete: Cascade) + userId String +} + +// Weak entity +model Settings { + userId String @unique + user User @relation(fields: [userId], references: [userId]) + is12HourMode Boolean + isDarkMode Boolean + isSquareEdges Boolean + isHideFullClasses Boolean + isDefaultUnscheduled Boolean + isHideClassInfo Boolean + isSortAlphabetic Boolean + isShowOnlyOpenClasses Boolean + isHideExamClasses Boolean + isConvertToLocalTimezone Boolean +} + +model Session { + id String @id + sid String @unique + data String @db.Text // MediumText may be needed for MySql + expiresAt DateTime +} + +// future: add settings for individual timetables, rounded corners, show only open classes etc? \ No newline at end of file diff --git a/server/src/app.controller.spec.ts b/server/src/app.controller.spec.ts new file mode 100644 index 000000000..d22f3890a --- /dev/null +++ b/server/src/app.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +describe('AppController', () => { + let appController: AppController; + + beforeEach(async () => { + const app: TestingModule = await Test.createTestingModule({ + controllers: [AppController], + providers: [AppService], + }).compile(); + + appController = app.get(AppController); + }); + + describe('root', () => { + it('should return "Hello World!"', () => { + expect(appController.getHello()).toBe('Hello World!'); + }); + }); +}); diff --git a/server/src/app.controller.ts b/server/src/app.controller.ts new file mode 100644 index 000000000..cce879ee6 --- /dev/null +++ b/server/src/app.controller.ts @@ -0,0 +1,12 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getHello(): string { + return this.appService.getHello(); + } +} diff --git a/server/src/app.module.ts b/server/src/app.module.ts new file mode 100644 index 000000000..86628031c --- /dev/null +++ b/server/src/app.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +@Module({ + imports: [], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule {} diff --git a/server/src/app.service.ts b/server/src/app.service.ts new file mode 100644 index 000000000..927d7cca0 --- /dev/null +++ b/server/src/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getHello(): string { + return 'Hello World!'; + } +} diff --git a/server/src/main.ts b/server/src/main.ts new file mode 100644 index 000000000..13cad38cf --- /dev/null +++ b/server/src/main.ts @@ -0,0 +1,8 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + await app.listen(3000); +} +bootstrap(); diff --git a/server/test/app.e2e-spec.ts b/server/test/app.e2e-spec.ts new file mode 100644 index 000000000..50cda6233 --- /dev/null +++ b/server/test/app.e2e-spec.ts @@ -0,0 +1,24 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { INestApplication } from '@nestjs/common'; +import * as request from 'supertest'; +import { AppModule } from './../src/app.module'; + +describe('AppController (e2e)', () => { + let app: INestApplication; + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + await app.init(); + }); + + it('/ (GET)', () => { + return request(app.getHttpServer()) + .get('/') + .expect(200) + .expect('Hello World!'); + }); +}); diff --git a/server/test/jest-e2e.json b/server/test/jest-e2e.json new file mode 100644 index 000000000..e9d912f3e --- /dev/null +++ b/server/test/jest-e2e.json @@ -0,0 +1,9 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": ".", + "testEnvironment": "node", + "testRegex": ".e2e-spec.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + } +} diff --git a/server/tsconfig.build.json b/server/tsconfig.build.json new file mode 100644 index 000000000..64f86c6bd --- /dev/null +++ b/server/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/server/tsconfig.json b/server/tsconfig.json index 99e22acbb..95f5641cf 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -1,7 +1,21 @@ { "compilerOptions": { - "types": ["node"], - "resolveJsonModule": true, - "outDir": "./dist" + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false } } diff --git a/server_old/.gitignore b/server_old/.gitignore new file mode 100644 index 000000000..7aca60aa5 --- /dev/null +++ b/server_old/.gitignore @@ -0,0 +1,4 @@ +data/ +dist/ +.DS_Store + diff --git a/server/.npmrc b/server_old/.npmrc similarity index 100% rename from server/.npmrc rename to server_old/.npmrc diff --git a/server_old/README.md b/server_old/README.md new file mode 100644 index 000000000..3e628e895 --- /dev/null +++ b/server_old/README.md @@ -0,0 +1,30 @@ +# Notangles Server + +The Notangles server allows the client to communicate with the autotimetabling server. + +## Installation + +The server has been verified to work with: + +- npm v8.3.1 +- node v16.14.0 + +In the root server directory `server`, run `npm install` to install all the dependencies. + +## Running + +Run `npm start` to start the server locally. The server will be hosted at http://localhost:3001. + +## Tech Stack + +The Notangles server uses: + +- [MongoDB](https://www.mongodb.com/) +- [TypeScript](https://www.typescriptlang.org/) +- [Express](https://expressjs.com/) + +## API endpoints + +### `POST /auto` + +Returns a list of ints that correspond to class times for the inputted data diff --git a/server/autotimetabler.proto b/server_old/autotimetabler.proto similarity index 100% rename from server/autotimetabler.proto rename to server_old/autotimetabler.proto diff --git a/server_old/package.json b/server_old/package.json new file mode 100644 index 000000000..b0e28d452 --- /dev/null +++ b/server_old/package.json @@ -0,0 +1,37 @@ +{ + "name": "notangles-server", + "version": "1.0.0", + "private": true, + "description": "", + "main": "app.js", + "scripts": { + "start": "NODE_ENV=DEV ts-node server.ts", + "start:production": "NODE_ENV=PROD node server.js", + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc", + "prettier-format": "prettier 'src/*.ts' 'src/controllers/*.ts' --write", + "proto:gen": "./src/proto-gen.sh" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@sentry/node": "7.84.0", + "@sentry/tracing": "7.84.0", + "@grpc/grpc-js": "1.9.12", + "body-parser": "1.20.2", + "buffer-from": "1.1.2", + "express": "4.18.2", + "google-protobuf": "3.21.2", + "grpc_tools_node_protoc_ts": "5.3.3", + "grpc-tools": "1.12.4", + "minimist": "1.2.8", + "ts-protoc-gen": "0.15.0" + }, + "devDependencies": { + "@types/express": "4.17.21", + "@types/node": "20.12.3", + "prettier": "3.1.0", + "ts-node": "10.9.1", + "typescript": "4.9.5" + } +} diff --git a/server_old/pnpm-lock.yaml b/server_old/pnpm-lock.yaml new file mode 100644 index 000000000..22800ef2d --- /dev/null +++ b/server_old/pnpm-lock.yaml @@ -0,0 +1,1338 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@grpc/grpc-js': + specifier: 1.9.12 + version: 1.9.12 + '@sentry/node': + specifier: 7.84.0 + version: 7.84.0 + '@sentry/tracing': + specifier: 7.84.0 + version: 7.84.0 + body-parser: + specifier: 1.20.2 + version: 1.20.2 + buffer-from: + specifier: 1.1.2 + version: 1.1.2 + express: + specifier: 4.18.2 + version: 4.18.2 + google-protobuf: + specifier: 3.21.2 + version: 3.21.2 + grpc-tools: + specifier: 1.12.4 + version: 1.12.4 + grpc_tools_node_protoc_ts: + specifier: 5.3.3 + version: 5.3.3 + minimist: + specifier: 1.2.8 + version: 1.2.8 + ts-protoc-gen: + specifier: 0.15.0 + version: 0.15.0 + +devDependencies: + '@types/express': + specifier: 4.17.21 + version: 4.17.21 + '@types/node': + specifier: 20.12.3 + version: 20.12.3 + prettier: + specifier: 3.1.0 + version: 3.1.0 + ts-node: + specifier: 10.9.1 + version: 10.9.1(@types/node@20.12.3)(typescript@4.9.5) + typescript: + specifier: 4.9.5 + version: 4.9.5 + +packages: + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + + /@grpc/grpc-js@1.9.12: + resolution: {integrity: sha512-Um5MBuge32TS3lAKX02PGCnFM4xPT996yLgZNb5H03pn6NyJ4Iwn5YcPq6Jj9yxGRk7WOgaZFtVRH5iTdYBeUg==} + engines: {node: ^8.13.0 || >=10.10.0} + dependencies: + '@grpc/proto-loader': 0.7.10 + '@types/node': 20.12.3 + dev: false + + /@grpc/proto-loader@0.7.10: + resolution: {integrity: sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + lodash.camelcase: 4.3.0 + long: 5.2.3 + protobufjs: 7.2.5 + yargs: 17.7.2 + dev: false + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@mapbox/node-pre-gyp@1.0.11: + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + dependencies: + detect-libc: 2.0.2 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.7.0 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.5.4 + tar: 6.2.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@protobufjs/aspromise@1.1.2: + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + dev: false + + /@protobufjs/base64@1.1.2: + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + dev: false + + /@protobufjs/codegen@2.0.4: + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + dev: false + + /@protobufjs/eventemitter@1.1.0: + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + dev: false + + /@protobufjs/fetch@1.1.0: + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + dev: false + + /@protobufjs/float@1.0.2: + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + dev: false + + /@protobufjs/inquire@1.1.0: + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + dev: false + + /@protobufjs/path@1.1.2: + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + dev: false + + /@protobufjs/pool@1.1.0: + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + dev: false + + /@protobufjs/utf8@1.1.0: + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + dev: false + + /@sentry-internal/tracing@7.84.0: + resolution: {integrity: sha512-y9bGYA0OM6PEREfd+nk4UURZy29tpIw+7vQwpxWfEVs2fqq0/5TBFX/tKFb8AKUI9lVM8v0bcF0bNSCnuPQZHQ==} + engines: {node: '>=8'} + dependencies: + '@sentry/core': 7.84.0 + '@sentry/types': 7.84.0 + '@sentry/utils': 7.84.0 + dev: false + + /@sentry/core@7.84.0: + resolution: {integrity: sha512-tbuwunbBx2kSex15IHCqHDnrMfIlqPc6w/76fwkGqokz3oh9GSEGlLICwmBWL8AypWimUg13IDtFpD0TJTriWA==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.84.0 + '@sentry/utils': 7.84.0 + dev: false + + /@sentry/node@7.84.0: + resolution: {integrity: sha512-Xm3fIXT3TZOQi+6uQBavI8iOehD3PkY7v0y3hog0d4lQTH88vQK9BBsI+jZEq81Em+RG/u7vZNiFo6YMTnWF7Q==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.84.0 + '@sentry/core': 7.84.0 + '@sentry/types': 7.84.0 + '@sentry/utils': 7.84.0 + https-proxy-agent: 5.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@sentry/tracing@7.84.0: + resolution: {integrity: sha512-NhBX28vUmCu/5avyGKX6B4UTm4MTOfbdg9ZzCnS7hPuWDfEAUIVHZVryi2q8bqp2DNGJvS9qIq/TSf39JIpdJg==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.84.0 + dev: false + + /@sentry/types@7.84.0: + resolution: {integrity: sha512-VqGLIF3JOUrk7yIXjLXJvAORkZL1e3dDX0Q1okRehwyt/5CRE+mdUTeJZkBo9P9mBwgMyvtwklzOGGrzjb4eMA==} + engines: {node: '>=8'} + dev: false + + /@sentry/utils@7.84.0: + resolution: {integrity: sha512-qdUVuxnRBvaf05AU+28R+xYtZmi/Ymf8os3Njq9g4XuA+QEkZLbzmIpRK5W9Ja7vUtjOeg29Xgg43A8znde9LQ==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.84.0 + dev: false + + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: true + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@types/body-parser@1.19.3: + resolution: {integrity: sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==} + dependencies: + '@types/connect': 3.4.36 + '@types/node': 20.12.3 + dev: true + + /@types/connect@3.4.36: + resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} + dependencies: + '@types/node': 20.12.3 + dev: true + + /@types/express-serve-static-core@4.17.37: + resolution: {integrity: sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==} + dependencies: + '@types/node': 20.12.3 + '@types/qs': 6.9.8 + '@types/range-parser': 1.2.5 + '@types/send': 0.17.2 + dev: true + + /@types/express@4.17.21: + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + dependencies: + '@types/body-parser': 1.19.3 + '@types/express-serve-static-core': 4.17.37 + '@types/qs': 6.9.8 + '@types/serve-static': 1.15.3 + dev: true + + /@types/http-errors@2.0.2: + resolution: {integrity: sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==} + dev: true + + /@types/mime@1.3.3: + resolution: {integrity: sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==} + dev: true + + /@types/mime@3.0.2: + resolution: {integrity: sha512-Wj+fqpTLtTbG7c0tH47dkahefpLKEbB+xAZuLq7b4/IDHPl/n6VoXcyUQ2bypFlbSwvCr0y+bD4euTTqTJsPxQ==} + dev: true + + /@types/node@20.12.3: + resolution: {integrity: sha512-sD+ia2ubTeWrOu+YMF+MTAB7E+O7qsMqAbMfW7DG3K1URwhZ5hN1pLlRVGbf4wDFzSfikL05M17EyorS86jShw==} + dependencies: + undici-types: 5.26.5 + + /@types/qs@6.9.8: + resolution: {integrity: sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==} + dev: true + + /@types/range-parser@1.2.5: + resolution: {integrity: sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==} + dev: true + + /@types/send@0.17.2: + resolution: {integrity: sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==} + dependencies: + '@types/mime': 1.3.3 + '@types/node': 20.12.3 + dev: true + + /@types/serve-static@1.15.3: + resolution: {integrity: sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==} + dependencies: + '@types/http-errors': 2.0.2 + '@types/mime': 3.0.2 + '@types/node': 20.12.3 + dev: true + + /abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: false + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: false + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: false + + /aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: false + + /are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + dev: false + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: false + + /body-parser@1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: false + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: false + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + dev: false + + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: false + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: false + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: false + + /color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: false + + /console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: false + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + dev: false + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: false + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /express@4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: false + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: false + + /gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + + /get-intrinsic@1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.4 + has-proto: 1.0.1 + has-symbols: 1.0.3 + dev: false + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + + /google-protobuf@3.15.8: + resolution: {integrity: sha512-2jtfdqTaSxk0cuBJBtTTWsot4WtR9RVr2rXg7x7OoqiuOKopPrwXpM1G4dXIkLcUNRh3RKzz76C8IOkksZSeOw==} + dev: false + + /google-protobuf@3.21.2: + resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==} + dev: false + + /grpc-tools@1.12.4: + resolution: {integrity: sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==} + hasBin: true + requiresBuild: true + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /grpc_tools_node_protoc_ts@5.3.3: + resolution: {integrity: sha512-M/YrklvVXMtuuj9kb42PxeouZhs7Ul+R4e/31XwrankUcKL8cQQP50Q9q+KEHGyHQaPt6VtKKsxMgLaKbCxeww==} + hasBin: true + dependencies: + google-protobuf: 3.15.8 + handlebars: 4.7.7 + dev: false + + /handlebars@4.7.7: + resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + dev: false + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: false + + /has@1.0.4: + resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} + engines: {node: '>= 0.4.0'} + dev: false + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: false + + /long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + dev: false + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + dev: false + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: false + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: false + + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: false + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: false + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: false + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + + /npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + dev: false + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: false + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: false + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: false + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: false + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /prettier@3.1.0: + resolution: {integrity: sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /protobufjs@7.2.5: + resolution: {integrity: sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==} + engines: {node: '>=12.0.0'} + requiresBuild: true + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.12.3 + long: 5.2.3 + dev: false + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: false + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: false + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: false + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + object-inspect: 1.12.3 + dev: false + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: false + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: false + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: false + + /tar@6.2.0: + resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: false + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /ts-node@10.9.1(@types/node@20.12.3)(typescript@4.9.5): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.12.3 + acorn: 8.10.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.9.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + + /ts-protoc-gen@0.15.0: + resolution: {integrity: sha512-TycnzEyrdVDlATJ3bWFTtra3SCiEP0W0vySXReAuEygXCUr1j2uaVyL0DhzjwuUdQoW5oXPwk6oZWeA0955V+g==} + hasBin: true + dependencies: + google-protobuf: 3.21.2 + dev: false + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /typescript@4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: false + + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: false + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: false + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: false + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true diff --git a/server/proto-gen.sh b/server_old/proto-gen.sh similarity index 100% rename from server/proto-gen.sh rename to server_old/proto-gen.sh diff --git a/server/server.ts b/server_old/server.ts similarity index 100% rename from server/server.ts rename to server_old/server.ts diff --git a/server/src/app.ts b/server_old/src/app.ts similarity index 100% rename from server/src/app.ts rename to server_old/src/app.ts diff --git a/server/src/config.ts b/server_old/src/config.ts similarity index 100% rename from server/src/config.ts rename to server_old/src/config.ts diff --git a/server/src/controllers/getAutotimetable.ts b/server_old/src/controllers/getAutotimetable.ts similarity index 100% rename from server/src/controllers/getAutotimetable.ts rename to server_old/src/controllers/getAutotimetable.ts diff --git a/server/src/controllers/index.ts b/server_old/src/controllers/index.ts similarity index 100% rename from server/src/controllers/index.ts rename to server_old/src/controllers/index.ts diff --git a/server/src/index.ts b/server_old/src/index.ts similarity index 100% rename from server/src/index.ts rename to server_old/src/index.ts diff --git a/server/src/proto/autotimetabler_grpc_pb.d.ts b/server_old/src/proto/autotimetabler_grpc_pb.d.ts similarity index 100% rename from server/src/proto/autotimetabler_grpc_pb.d.ts rename to server_old/src/proto/autotimetabler_grpc_pb.d.ts diff --git a/server/src/proto/autotimetabler_grpc_pb.js b/server_old/src/proto/autotimetabler_grpc_pb.js similarity index 100% rename from server/src/proto/autotimetabler_grpc_pb.js rename to server_old/src/proto/autotimetabler_grpc_pb.js diff --git a/server/src/proto/autotimetabler_pb.d.ts b/server_old/src/proto/autotimetabler_pb.d.ts similarity index 100% rename from server/src/proto/autotimetabler_pb.d.ts rename to server_old/src/proto/autotimetabler_pb.d.ts diff --git a/server/src/proto/autotimetabler_pb.js b/server_old/src/proto/autotimetabler_pb.js similarity index 100% rename from server/src/proto/autotimetabler_pb.js rename to server_old/src/proto/autotimetabler_pb.js diff --git a/server_old/tsconfig.json b/server_old/tsconfig.json new file mode 100644 index 000000000..99e22acbb --- /dev/null +++ b/server_old/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "types": ["node"], + "resolveJsonModule": true, + "outDir": "./dist" + } +} From 1407cb1321b9caa23f50608c9eb9033e0a83c9d0 Mon Sep 17 00:00:00 2001 From: ray Date: Fri, 10 May 2024 21:05:10 +1000 Subject: [PATCH 15/92] added nestjs support with auto timetabling --- client/src/api/config.ts | 1 - client/src/api/getAutoTimetable.ts | 1 + .../components/controls/Autotimetabler.tsx | 1 + server/Dockerfile | 49 +- {server_old => server}/autotimetabler.proto | 0 server/docker-compose.yaml | 18 +- server/nest-cli.json | 5 +- server/package.json | 9 +- server/pnpm-lock.yaml | 393 ++++- {server_old => server}/proto-gen.sh | 0 server/src/app.module.ts | 3 +- server/src/auto/auto.controller.ts | 18 + server/src/auto/auto.module.ts | 9 + .../src/auto/auto.service.ts | 35 +- server/src/auto/dto/auto.dto.ts | 12 + {server_old => server}/src/config.ts | 0 server/src/main.ts | 6 +- .../src/proto/autotimetabler_grpc_pb.d.ts | 0 .../src/proto/autotimetabler_grpc_pb.js | 0 .../src/proto/autotimetabler_pb.d.ts | 0 .../src/proto/autotimetabler_pb.js | 0 server_old/.gitignore | 4 - server_old/.npmrc | 2 - server_old/README.md | 30 - server_old/package.json | 37 - server_old/pnpm-lock.yaml | 1338 ----------------- server_old/server.ts | 23 - server_old/src/app.ts | 25 - server_old/src/controllers/index.ts | 3 - server_old/src/index.ts | 5 - server_old/tsconfig.json | 7 - 31 files changed, 464 insertions(+), 1570 deletions(-) rename {server_old => server}/autotimetabler.proto (100%) rename {server_old => server}/proto-gen.sh (100%) mode change 100644 => 100755 create mode 100644 server/src/auto/auto.controller.ts create mode 100644 server/src/auto/auto.module.ts rename server_old/src/controllers/getAutotimetable.ts => server/src/auto/auto.service.ts (56%) create mode 100644 server/src/auto/dto/auto.dto.ts rename {server_old => server}/src/config.ts (100%) rename {server_old => server}/src/proto/autotimetabler_grpc_pb.d.ts (100%) rename {server_old => server}/src/proto/autotimetabler_grpc_pb.js (100%) rename {server_old => server}/src/proto/autotimetabler_pb.d.ts (100%) rename {server_old => server}/src/proto/autotimetabler_pb.js (100%) delete mode 100644 server_old/.gitignore delete mode 100644 server_old/.npmrc delete mode 100644 server_old/README.md delete mode 100644 server_old/package.json delete mode 100644 server_old/pnpm-lock.yaml delete mode 100644 server_old/server.ts delete mode 100644 server_old/src/app.ts delete mode 100644 server_old/src/controllers/index.ts delete mode 100644 server_old/src/index.ts delete mode 100644 server_old/tsconfig.json diff --git a/client/src/api/config.ts b/client/src/api/config.ts index da58fa147..c918057c1 100644 --- a/client/src/api/config.ts +++ b/client/src/api/config.ts @@ -19,5 +19,4 @@ const API_CONFIG: Record = Object.freeze({ [Env.MOCK]: { timetable: `${LIVE}/api`, auto: `${LOCAL}/auto` }, [Env.PROD]: { timetable: `${LIVE}/api`, auto: `${LIVE}/auto` }, }); - export const API_URL: Config = API_CONFIG[import.meta.env.VITE_APP_ENVIRONMENT || Env.DEV]; diff --git a/client/src/api/getAutoTimetable.ts b/client/src/api/getAutoTimetable.ts index 4ee00a09e..f343a2fb7 100644 --- a/client/src/api/getAutoTimetable.ts +++ b/client/src/api/getAutoTimetable.ts @@ -2,6 +2,7 @@ import NetworkError from '../interfaces/NetworkError'; import { API_URL } from './config'; const getAutoTimetable = async (data: any): Promise<[number[], boolean]> => { + console.log(`${API_URL.auto}`); try { const res = await fetch(`${API_URL.auto}`, { method: 'POST', diff --git a/client/src/components/controls/Autotimetabler.tsx b/client/src/components/controls/Autotimetabler.tsx index 857980425..543a2a028 100644 --- a/client/src/components/controls/Autotimetabler.tsx +++ b/client/src/components/controls/Autotimetabler.tsx @@ -192,6 +192,7 @@ const Autotimetabler: React.FC = ({ handleSelectClass }) => ]; try { + console.log(timetableData); const [resultsWithEvents, isOptimal] = await getAutoTimetable(timetableData); const results = resultsWithEvents.slice(0, targetActivities.current.length); diff --git a/server/Dockerfile b/server/Dockerfile index c873db6bd..fed6c4259 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,46 +1,25 @@ -# # Dependency versions should be pinned -# FROM node:21.0.0-alpine as builder -# RUN npm i -g pnpm -# WORKDIR /server - -# COPY package.json pnpm-lock.yaml ./ -# RUN pnpm i --frozen-lockfile - -# COPY . . -# RUN pnpm run build - - -# FROM node:21.0.0-alpine -# RUN npm i -g pnpm -# WORKDIR /server - -# ENV NODE_ENV production -# COPY package.json pnpm-lock.yaml ./ -# RUN pnpm install --production - -# # COPY --from=builder /server/dist . -# # COPY ./src/proto/*.js ./src/proto/ +# Dependency versions should be pinned +FROM node:21.0.0-alpine as builder +RUN npm i -g pnpm +RUN pnpm install @nestjs/cli +WORKDIR /server -# EXPOSE 3001 +COPY package.json pnpm-lock.yaml ./ +RUN pnpm i --frozen-lockfile -# CMD ["pnpm", "run", "start:prod"] +COPY . . +RUN pnpm run build -# Use an official Node.js image as the base image FROM node:21.0.0-alpine -RUN npm i -g pnpm - -# Set the working directory inside the container WORKDIR /server +RUN npm i -g pnpm -# Copy package.json and pnpm-lock.yaml to the working directory +ENV NODE_ENV production COPY package.json pnpm-lock.yaml ./ -RUN pnpm install --frozen-lockfile +RUN pnpm install --production -# Copy the rest of the application code -COPY . . +COPY --from=builder /server . -# Expose the port your application listens on EXPOSE 3001 -# Command to run your application using PNPM -CMD ["pnpm", "run", "start"] \ No newline at end of file +CMD ["pnpm", "run", "start:prod"] diff --git a/server_old/autotimetabler.proto b/server/autotimetabler.proto similarity index 100% rename from server_old/autotimetabler.proto rename to server/autotimetabler.proto diff --git a/server/docker-compose.yaml b/server/docker-compose.yaml index 8ca589149..ebf74fe85 100644 --- a/server/docker-compose.yaml +++ b/server/docker-compose.yaml @@ -1,4 +1,4 @@ -version: "3.7" +version: '3.7' services: server: container_name: notangles-server @@ -8,14 +8,22 @@ services: depends_on: - database.notangles-db ports: - - "3001:3001" + - '3001:3001' links: - database.notangles-db + database.notangles-db: container_name: notangles-database restart: always - image: mongo:7.0 + image: postgres:alpine ports: - - "27017:27017" + - '5432:5432' + environment: + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_DB=${POSTGRES_DB} volumes: - - ~/var/lib/notangles/data:/data/db + - postgres:/var/lib/postgresql/data +volumes: + postgres: + name: server \ No newline at end of file diff --git a/server/nest-cli.json b/server/nest-cli.json index f9aa683b1..b4625a634 100644 --- a/server/nest-cli.json +++ b/server/nest-cli.json @@ -3,6 +3,9 @@ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { - "deleteOutDir": true + "deleteOutDir": true, + "assets": [ + "./proto/*" + ] } } diff --git a/server/package.json b/server/package.json index 2617d65c6..deffa6f6a 100644 --- a/server/package.json +++ b/server/package.json @@ -20,12 +20,19 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { + "@grpc/grpc-js": "^1.10.7", "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", + "@nestjs/mapped-types": "*", "@nestjs/platform-express": "^10.0.0", "@prisma/client": "5.13.0", + "class-validator": "^0.14.1", + "google-protobuf": "^3.21.2", + "grpc_tools_node_protoc_ts": "^5.3.3", + "protobufjs": "4.1.3", "reflect-metadata": "^0.2.0", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "ts-protoc-gen": "^0.15.0" }, "devDependencies": { "@nestjs/cli": "^10.0.0", diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index 60bb2d46c..ecfb713a7 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -5,24 +5,45 @@ settings: excludeLinksFromLockfile: false dependencies: + '@grpc/grpc-js': + specifier: ^1.10.7 + version: 1.10.7 '@nestjs/common': specifier: ^10.0.0 - version: 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + version: 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/core': specifier: ^10.0.0 version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/mapped-types': + specifier: '*' + version: 2.0.5(@nestjs/common@10.3.8)(class-validator@0.14.1)(reflect-metadata@0.2.2) '@nestjs/platform-express': specifier: ^10.0.0 version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) '@prisma/client': specifier: 5.13.0 version: 5.13.0(prisma@5.13.0) + class-validator: + specifier: ^0.14.1 + version: 0.14.1 + google-protobuf: + specifier: ^3.21.2 + version: 3.21.2 + grpc_tools_node_protoc_ts: + specifier: ^5.3.3 + version: 5.3.3 + protobufjs: + specifier: 4.1.3 + version: 4.1.3 reflect-metadata: specifier: ^0.2.0 version: 0.2.2 rxjs: specifier: ^7.8.1 version: 7.8.1 + ts-protoc-gen: + specifier: ^0.15.0 + version: 0.15.0 devDependencies: '@nestjs/cli': @@ -529,6 +550,25 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@grpc/grpc-js@1.10.7: + resolution: {integrity: sha512-ZMBVjSeDAz3tFSehyO6Pd08xZT1HfIwq3opbeM4cDlBh52gmwp0wVIPcQur53NN0ac68HMZ/7SF2rGRD5KmVmg==} + engines: {node: '>=12.10.0'} + dependencies: + '@grpc/proto-loader': 0.7.13 + '@js-sdsl/ordered-map': 4.4.2 + dev: false + + /@grpc/proto-loader@0.7.13: + resolution: {integrity: sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==} + engines: {node: '>=6'} + hasBin: true + dependencies: + lodash.camelcase: 4.3.0 + long: 5.2.3 + protobufjs: 7.2.6 + yargs: 17.7.2 + dev: false + /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -835,6 +875,10 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@js-sdsl/ordered-map@4.4.2: + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + dev: false + /@ljharb/through@2.3.13: resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==} engines: {node: '>= 0.4'} @@ -887,7 +931,7 @@ packages: - webpack-cli dev: true - /@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1): + /@nestjs/common@10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1): resolution: {integrity: sha512-P+vPEIvqx2e+fonsYVlFXKvoChyJ8Tq+lfpqdVFqblovHbFr3kZ/nYX0cPs+XuW6bnRT8tz0SSR9XBGU43kJhw==} peerDependencies: class-transformer: '*' @@ -900,6 +944,7 @@ packages: class-validator: optional: true dependencies: + class-validator: 0.14.1 iterare: 1.2.1 reflect-metadata: 0.2.2 rxjs: 7.8.1 @@ -924,7 +969,7 @@ packages: '@nestjs/websockets': optional: true dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) '@nuxtjs/opencollective': 0.3.2 fast-safe-stringify: 2.1.1 @@ -937,13 +982,31 @@ packages: transitivePeerDependencies: - encoding + /@nestjs/mapped-types@2.0.5(@nestjs/common@10.3.8)(class-validator@0.14.1)(reflect-metadata@0.2.2): + resolution: {integrity: sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + class-transformer: ^0.4.0 || ^0.5.0 + class-validator: ^0.13.0 || ^0.14.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + dependencies: + '@nestjs/common': 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + class-validator: 0.14.1 + reflect-metadata: 0.2.2 + dev: false + /@nestjs/platform-express@10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8): resolution: {integrity: sha512-sifLoxgEJvAgbim1UuW6wyScMfkS9SVQRH+lN33N/9ZvZSjO6NSDLOe+wxqsnZkia+QrjFC0qy0ITRAsggfqbg==} peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/core': ^10.0.0 dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) body-parser: 1.20.2 cors: 2.8.5 @@ -996,7 +1059,7 @@ packages: '@nestjs/platform-express': optional: true dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) tslib: 2.6.2 @@ -1086,6 +1149,49 @@ packages: dependencies: '@prisma/debug': 5.13.0 + /@protobufjs/aspromise@1.1.2: + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + dev: false + + /@protobufjs/base64@1.1.2: + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + dev: false + + /@protobufjs/codegen@2.0.4: + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + dev: false + + /@protobufjs/eventemitter@1.1.0: + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + dev: false + + /@protobufjs/fetch@1.1.0: + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + dev: false + + /@protobufjs/float@1.0.2: + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + dev: false + + /@protobufjs/inquire@1.1.0: + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + dev: false + + /@protobufjs/path@1.1.2: + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + dev: false + + /@protobufjs/pool@1.1.0: + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + dev: false + + /@protobufjs/utf8@1.1.0: + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + dev: false + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -1249,7 +1355,6 @@ packages: resolution: {integrity: sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw==} dependencies: undici-types: 5.26.5 - dev: true /@types/qs@6.9.15: resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} @@ -1297,6 +1402,9 @@ packages: '@types/superagent': 8.1.7 dev: true + /@types/validator@13.11.9: + resolution: {integrity: sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==} + /@types/yargs-parser@21.0.3: resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} dev: true @@ -1640,10 +1748,14 @@ packages: type-fest: 0.21.3 dev: true + /ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + dev: false + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - dev: true /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} @@ -1714,6 +1826,13 @@ packages: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} dev: true + /ascli@1.0.1: + resolution: {integrity: sha512-JGQaNxpaCJz9Bd1JvVaFIHuWn9S+l3xhN17R0V/vmUDiGE0QngNMXhjlqpwqV+91plWz9Fg+Lt28Lj7p5vjs8A==} + dependencies: + colour: 0.7.1 + optjs: 3.2.2 + dev: false + /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: true @@ -1792,7 +1911,6 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -1835,7 +1953,6 @@ packages: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} @@ -1884,12 +2001,25 @@ packages: ieee754: 1.2.1 dev: true + /bufferview@1.0.1: + resolution: {integrity: sha512-q87jdvsZ/sEngmDUvPT/PJsBGCi998c3B1U/6IN1uGg+R2HrTFJUDccXZEx6OxpuLySyBDGXc7vkSt4BXTyKxA==} + engines: {node: '>=0.8'} + dev: false + /busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} dependencies: streamsearch: 1.1.0 + /bytebuffer@4.1.0: + resolution: {integrity: sha512-iUP8IfllRZiCGYACmcE7IxEfW+L1OKUEcHhXsrosqf51HnwR55THbePWeY3xAFxMlhhUa2I6x3cp5zG2vHI2YQ==} + engines: {node: '>=0.8'} + dependencies: + bufferview: 1.0.1 + long: 2.4.0 + dev: false + /bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -1909,6 +2039,11 @@ packages: engines: {node: '>=6'} dev: true + /camelcase@2.1.1: + resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==} + engines: {node: '>=0.10.0'} + dev: false + /camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -1982,6 +2117,13 @@ packages: resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} dev: true + /class-validator@0.14.1: + resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==} + dependencies: + '@types/validator': 13.11.9 + libphonenumber-js: 1.11.1 + validator: 13.12.0 + /cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -2013,6 +2155,14 @@ packages: engines: {node: '>= 12'} dev: true + /cliui@3.2.0: + resolution: {integrity: sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==} + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + wrap-ansi: 2.1.0 + dev: false + /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -2020,7 +2170,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} @@ -2032,6 +2181,11 @@ packages: engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} dev: true + /code-point-at@1.1.0: + resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} + engines: {node: '>=0.10.0'} + dev: false + /collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} dev: true @@ -2055,6 +2209,11 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + /colour@0.7.1: + resolution: {integrity: sha512-Rel466v0EnmKPcsxHo91L4kgPs/6XF7Pu2LJNszq9lXYwi5CFWEeIiRaTX5ym7PPMdj4udDHkLSVC1//JVkZQg==} + engines: {node: '>=0.8'} + dev: false + /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -2088,7 +2247,6 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true /concat-stream@1.6.2: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} @@ -2207,6 +2365,11 @@ packages: ms: 2.1.2 dev: true + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: false + /dedent@1.5.3: resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} peerDependencies: @@ -2306,7 +2469,6 @@ packages: /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} @@ -2347,7 +2509,6 @@ packages: /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} - dev: true /escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -2808,7 +2969,6 @@ packages: /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - dev: true /get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} @@ -2860,6 +3020,16 @@ packages: path-scurry: 1.10.2 dev: true + /glob@5.0.15: + resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} + dependencies: + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -2905,6 +3075,14 @@ packages: slash: 3.0.0 dev: true + /google-protobuf@3.15.8: + resolution: {integrity: sha512-2jtfdqTaSxk0cuBJBtTTWsot4WtR9RVr2rXg7x7OoqiuOKopPrwXpM1G4dXIkLcUNRh3RKzz76C8IOkksZSeOw==} + dev: false + + /google-protobuf@3.21.2: + resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==} + dev: false + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -2918,6 +3096,27 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /grpc_tools_node_protoc_ts@5.3.3: + resolution: {integrity: sha512-M/YrklvVXMtuuj9kb42PxeouZhs7Ul+R4e/31XwrankUcKL8cQQP50Q9q+KEHGyHQaPt6VtKKsxMgLaKbCxeww==} + hasBin: true + dependencies: + google-protobuf: 3.15.8 + handlebars: 4.7.7 + dev: false + + /handlebars@4.7.7: + resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + dev: false + /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -3017,7 +3216,6 @@ packages: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -3069,6 +3267,11 @@ packages: engines: {node: '>= 0.10'} dev: true + /invert-kv@1.0.0: + resolution: {integrity: sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==} + engines: {node: '>=0.10.0'} + dev: false + /ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -3095,10 +3298,16 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-fullwidth-code-point@1.0.0: + resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==} + engines: {node: '>=0.10.0'} + dependencies: + number-is-nan: 1.0.1 + dev: false + /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - dev: true /is-generator-fn@2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} @@ -3719,6 +3928,13 @@ packages: engines: {node: '>=6'} dev: true + /lcid@1.0.0: + resolution: {integrity: sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==} + engines: {node: '>=0.10.0'} + dependencies: + invert-kv: 1.0.0 + dev: false + /leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -3732,6 +3948,9 @@ packages: type-check: 0.4.0 dev: true + /libphonenumber-js@1.11.1: + resolution: {integrity: sha512-Wze1LPwcnzvcKGcRHFGFECTaLzxOtujwpf924difr5zniyYv1C2PiW0419qDR7m8lKDxsImu5mwxFuXhXpjmvw==} + /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true @@ -3755,6 +3974,10 @@ packages: p-locate: 5.0.0 dev: true + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: false + /lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} dev: true @@ -3775,6 +3998,15 @@ packages: is-unicode-supported: 0.1.0 dev: true + /long@2.4.0: + resolution: {integrity: sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ==} + engines: {node: '>=0.6'} + dev: false + + /long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + dev: false + /lru-cache@10.2.2: resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} engines: {node: 14 || >=16.14} @@ -3882,7 +4114,6 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: true /minimatch@8.0.4: resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} @@ -3965,7 +4196,6 @@ packages: /neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true /node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} @@ -4008,6 +4238,11 @@ packages: path-key: 3.1.1 dev: true + /number-is-nan@1.0.1: + resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} + engines: {node: '>=0.10.0'} + dev: false + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -4025,7 +4260,6 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 - dev: true /onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} @@ -4046,6 +4280,10 @@ packages: word-wrap: 1.2.5 dev: true + /optjs@3.2.2: + resolution: {integrity: sha512-f8lTJm4LKirX+45xsFhuRNjA4f46QVLQKfGoNH7e2AEWS+24eM4XNH4pQ8Tw2LISCIvbST/wNcLdtgvgcqVaxA==} + dev: false + /ora@5.4.1: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} @@ -4061,6 +4299,13 @@ packages: wcwidth: 1.0.1 dev: true + /os-locale@1.4.0: + resolution: {integrity: sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==} + engines: {node: '>=0.10.0'} + dependencies: + lcid: 1.0.0 + dev: false + /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -4128,7 +4373,6 @@ packages: /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - dev: true /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} @@ -4235,6 +4479,36 @@ packages: sisteransi: 1.0.5 dev: true + /protobufjs@4.1.3: + resolution: {integrity: sha512-0oPzT65x/LgLTWQosf3Qi69nMCV6/bszfjRFdfBNVIYQmiiwJdn8DLKZLlga1dN1MkE6EZXvuWNOj0kTZK5R9Q==} + engines: {node: '>=0.8'} + hasBin: true + dependencies: + ascli: 1.0.1 + bytebuffer: 4.1.0 + glob: 5.0.15 + yargs: 3.32.0 + dev: false + + /protobufjs@7.2.6: + resolution: {integrity: sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==} + engines: {node: '>=12.0.0'} + requiresBuild: true + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.12.10 + long: 5.2.3 + dev: false + /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -4336,7 +4610,6 @@ packages: /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - dev: true /require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} @@ -4571,7 +4844,6 @@ packages: /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - dev: true /source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} @@ -4605,6 +4877,15 @@ packages: strip-ansi: 6.0.1 dev: true + /string-width@1.0.2: + resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} + engines: {node: '>=0.10.0'} + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + dev: false + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -4612,7 +4893,6 @@ packages: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true /string-width@5.1.2: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} @@ -4634,12 +4914,18 @@ packages: safe-buffer: 5.2.1 dev: true + /strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: false + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 - dev: true /strip-ansi@7.1.0: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} @@ -4941,6 +5227,13 @@ packages: yn: 3.1.1 dev: true + /ts-protoc-gen@0.15.0: + resolution: {integrity: sha512-TycnzEyrdVDlATJ3bWFTtra3SCiEP0W0vySXReAuEygXCUr1j2uaVyL0DhzjwuUdQoW5oXPwk6oZWeA0955V+g==} + hasBin: true + dependencies: + google-protobuf: 3.21.2 + dev: false + /tsconfig-paths-webpack-plugin@4.1.0: resolution: {integrity: sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==} engines: {node: '>=10.13.0'} @@ -5006,6 +5299,14 @@ packages: hasBin: true dev: true + /uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + /uid@2.0.2: resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} engines: {node: '>=8'} @@ -5014,7 +5315,6 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} @@ -5062,6 +5362,10 @@ packages: convert-source-map: 2.0.0 dev: true + /validator@13.12.0: + resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} + engines: {node: '>= 0.10'} + /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -5193,11 +5497,29 @@ packages: isexe: 2.0.0 dev: true + /window-size@0.1.4: + resolution: {integrity: sha512-2thx4pB0cV3h+Bw7QmMXcEbdmOzv9t0HFplJH/Lz6yu60hXYy5RT8rUu+wlIreVxWsGN20mo+MHeCSfUpQBwPw==} + engines: {node: '>= 0.10.0'} + hasBin: true + dev: false + /word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} dev: true + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: false + + /wrap-ansi@2.1.0: + resolution: {integrity: sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==} + engines: {node: '>=0.10.0'} + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + dev: false + /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -5214,7 +5536,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true /wrap-ansi@8.1.0: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} @@ -5227,7 +5548,6 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true /write-file-atomic@4.0.2: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} @@ -5241,10 +5561,13 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} + /y18n@3.2.2: + resolution: {integrity: sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==} + dev: false + /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - dev: true /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -5257,7 +5580,6 @@ packages: /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - dev: true /yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} @@ -5270,7 +5592,18 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: true + + /yargs@3.32.0: + resolution: {integrity: sha512-ONJZiimStfZzhKamYvR/xvmgW3uEkAUFSP91y2caTEPhzF6uP2JfPiVZcq66b/YR0C3uitxSV7+T1x8p5bkmMg==} + dependencies: + camelcase: 2.1.1 + cliui: 3.2.0 + decamelize: 1.2.0 + os-locale: 1.4.0 + string-width: 1.0.2 + window-size: 0.1.4 + y18n: 3.2.2 + dev: false /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} diff --git a/server_old/proto-gen.sh b/server/proto-gen.sh old mode 100644 new mode 100755 similarity index 100% rename from server_old/proto-gen.sh rename to server/proto-gen.sh diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 86628031c..acf0dfcab 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -1,9 +1,10 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; +import { AutoModule } from './auto/auto.module'; @Module({ - imports: [], + imports: [AutoModule], controllers: [AppController], providers: [AppService], }) diff --git a/server/src/auto/auto.controller.ts b/server/src/auto/auto.controller.ts new file mode 100644 index 000000000..cb652f31f --- /dev/null +++ b/server/src/auto/auto.controller.ts @@ -0,0 +1,18 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { AutoService } from './auto.service'; +import { autoDTO } from './dto/auto.dto'; + + +@Controller('auto') +export class AutoController { + constructor(private readonly autoService: AutoService) {} + + @Post() + create(@Body() userRequestConstraints: autoDTO) { + return this.autoService.getAutoTimetable(userRequestConstraints); + } + +} + + + diff --git a/server/src/auto/auto.module.ts b/server/src/auto/auto.module.ts new file mode 100644 index 000000000..3335b8aa9 --- /dev/null +++ b/server/src/auto/auto.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { AutoService } from './auto.service'; +import { AutoController } from './auto.controller'; + +@Module({ + controllers: [AutoController], + providers: [AutoService], +}) +export class AutoModule {} diff --git a/server_old/src/controllers/getAutotimetable.ts b/server/src/auto/auto.service.ts similarity index 56% rename from server_old/src/controllers/getAutotimetable.ts rename to server/src/auto/auto.service.ts index bc5bbf90f..ca701703d 100644 --- a/server_old/src/controllers/getAutotimetable.ts +++ b/server/src/auto/auto.service.ts @@ -1,29 +1,23 @@ -import { Response, Request } from 'express'; +import { Body, HttpException, HttpStatus, Injectable } from '@nestjs/common'; import * as grpc from '@grpc/grpc-js'; import { TimetableConstraints } from '../proto/autotimetabler_pb'; import { AutoTimetablerClient } from '../proto/autotimetabler_grpc_pb'; -import { config } from '../config'; +import { autoDTO } from './dto/auto.dto'; +import { config } from 'src/config'; -interface ReqBodyData { - start: number; - end: number; - days: string; - gap: number; - maxdays: number, - periodInfoList: { - periodsPerClass: number; - periodTimes: Array; - durations: Array; - }[] -} +@Injectable() +export class AutoService { + async getAutoTimetable(@Body() autoService: autoDTO) { + return getAuto(autoService); + } +} -export const getAuto = async (req: Request, res: Response) => { - var client = new AutoTimetablerClient(config.auto, grpc.credentials.createInsecure()); +export const getAuto = async (data: autoDTO) => { + let client = new AutoTimetablerClient(config.auto, grpc.credentials.createInsecure()); const constraints = new TimetableConstraints(); - const data: ReqBodyData = req.body; constraints.setStart(data.start); constraints.setEnd(data.end); constraints.setDays(data.days); @@ -42,11 +36,10 @@ export const getAuto = async (req: Request, res: Response) => { client.findBestTimetable(constraints, (err, response) => { if (err) { - console.log('error was found: ' + err); - res.status(502).send('An error occurred when handling the request.') - + console.error('error was found: ' + err); + throw new HttpException('An error occurred when handling the request.', HttpStatus.BAD_GATEWAY); } else { - res.send(JSON.stringify({ given: response.getTimesList(), optimal: response.getOptimal() })); + return JSON.stringify({ given: response.getTimesList(), optimal: response.getOptimal()}); } }); }; diff --git a/server/src/auto/dto/auto.dto.ts b/server/src/auto/dto/auto.dto.ts new file mode 100644 index 000000000..34c73f4a8 --- /dev/null +++ b/server/src/auto/dto/auto.dto.ts @@ -0,0 +1,12 @@ +export class autoDTO { + start: number; + end: number; + days: string; + gap: number; + maxdays: number; + periodInfoList: { + periodsPerClass: number; + periodTimes: Array; + durations: Array; + }[] +} diff --git a/server_old/src/config.ts b/server/src/config.ts similarity index 100% rename from server_old/src/config.ts rename to server/src/config.ts diff --git a/server/src/main.ts b/server/src/main.ts index 13cad38cf..86c7a896b 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -3,6 +3,10 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); - await app.listen(3000); + app.enableCors({ + origin: 'http://localhost:5173', // Replace this in production. + credentials: true, // Allow credentials (e.g., cookies) to be sent with the request + }); + await app.listen(3001); } bootstrap(); diff --git a/server_old/src/proto/autotimetabler_grpc_pb.d.ts b/server/src/proto/autotimetabler_grpc_pb.d.ts similarity index 100% rename from server_old/src/proto/autotimetabler_grpc_pb.d.ts rename to server/src/proto/autotimetabler_grpc_pb.d.ts diff --git a/server_old/src/proto/autotimetabler_grpc_pb.js b/server/src/proto/autotimetabler_grpc_pb.js similarity index 100% rename from server_old/src/proto/autotimetabler_grpc_pb.js rename to server/src/proto/autotimetabler_grpc_pb.js diff --git a/server_old/src/proto/autotimetabler_pb.d.ts b/server/src/proto/autotimetabler_pb.d.ts similarity index 100% rename from server_old/src/proto/autotimetabler_pb.d.ts rename to server/src/proto/autotimetabler_pb.d.ts diff --git a/server_old/src/proto/autotimetabler_pb.js b/server/src/proto/autotimetabler_pb.js similarity index 100% rename from server_old/src/proto/autotimetabler_pb.js rename to server/src/proto/autotimetabler_pb.js diff --git a/server_old/.gitignore b/server_old/.gitignore deleted file mode 100644 index 7aca60aa5..000000000 --- a/server_old/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -data/ -dist/ -.DS_Store - diff --git a/server_old/.npmrc b/server_old/.npmrc deleted file mode 100644 index 16dde58b9..000000000 --- a/server_old/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -auto-install-peers=true -save-exact=true \ No newline at end of file diff --git a/server_old/README.md b/server_old/README.md deleted file mode 100644 index 3e628e895..000000000 --- a/server_old/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Notangles Server - -The Notangles server allows the client to communicate with the autotimetabling server. - -## Installation - -The server has been verified to work with: - -- npm v8.3.1 -- node v16.14.0 - -In the root server directory `server`, run `npm install` to install all the dependencies. - -## Running - -Run `npm start` to start the server locally. The server will be hosted at http://localhost:3001. - -## Tech Stack - -The Notangles server uses: - -- [MongoDB](https://www.mongodb.com/) -- [TypeScript](https://www.typescriptlang.org/) -- [Express](https://expressjs.com/) - -## API endpoints - -### `POST /auto` - -Returns a list of ints that correspond to class times for the inputted data diff --git a/server_old/package.json b/server_old/package.json deleted file mode 100644 index b0e28d452..000000000 --- a/server_old/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "notangles-server", - "version": "1.0.0", - "private": true, - "description": "", - "main": "app.js", - "scripts": { - "start": "NODE_ENV=DEV ts-node server.ts", - "start:production": "NODE_ENV=PROD node server.js", - "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc", - "prettier-format": "prettier 'src/*.ts' 'src/controllers/*.ts' --write", - "proto:gen": "./src/proto-gen.sh" - }, - "author": "", - "license": "ISC", - "dependencies": { - "@sentry/node": "7.84.0", - "@sentry/tracing": "7.84.0", - "@grpc/grpc-js": "1.9.12", - "body-parser": "1.20.2", - "buffer-from": "1.1.2", - "express": "4.18.2", - "google-protobuf": "3.21.2", - "grpc_tools_node_protoc_ts": "5.3.3", - "grpc-tools": "1.12.4", - "minimist": "1.2.8", - "ts-protoc-gen": "0.15.0" - }, - "devDependencies": { - "@types/express": "4.17.21", - "@types/node": "20.12.3", - "prettier": "3.1.0", - "ts-node": "10.9.1", - "typescript": "4.9.5" - } -} diff --git a/server_old/pnpm-lock.yaml b/server_old/pnpm-lock.yaml deleted file mode 100644 index 22800ef2d..000000000 --- a/server_old/pnpm-lock.yaml +++ /dev/null @@ -1,1338 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - '@grpc/grpc-js': - specifier: 1.9.12 - version: 1.9.12 - '@sentry/node': - specifier: 7.84.0 - version: 7.84.0 - '@sentry/tracing': - specifier: 7.84.0 - version: 7.84.0 - body-parser: - specifier: 1.20.2 - version: 1.20.2 - buffer-from: - specifier: 1.1.2 - version: 1.1.2 - express: - specifier: 4.18.2 - version: 4.18.2 - google-protobuf: - specifier: 3.21.2 - version: 3.21.2 - grpc-tools: - specifier: 1.12.4 - version: 1.12.4 - grpc_tools_node_protoc_ts: - specifier: 5.3.3 - version: 5.3.3 - minimist: - specifier: 1.2.8 - version: 1.2.8 - ts-protoc-gen: - specifier: 0.15.0 - version: 0.15.0 - -devDependencies: - '@types/express': - specifier: 4.17.21 - version: 4.17.21 - '@types/node': - specifier: 20.12.3 - version: 20.12.3 - prettier: - specifier: 3.1.0 - version: 3.1.0 - ts-node: - specifier: 10.9.1 - version: 10.9.1(@types/node@20.12.3)(typescript@4.9.5) - typescript: - specifier: 4.9.5 - version: 4.9.5 - -packages: - - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - - /@grpc/grpc-js@1.9.12: - resolution: {integrity: sha512-Um5MBuge32TS3lAKX02PGCnFM4xPT996yLgZNb5H03pn6NyJ4Iwn5YcPq6Jj9yxGRk7WOgaZFtVRH5iTdYBeUg==} - engines: {node: ^8.13.0 || >=10.10.0} - dependencies: - '@grpc/proto-loader': 0.7.10 - '@types/node': 20.12.3 - dev: false - - /@grpc/proto-loader@0.7.10: - resolution: {integrity: sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - lodash.camelcase: 4.3.0 - long: 5.2.3 - protobufjs: 7.2.5 - yargs: 17.7.2 - dev: false - - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@mapbox/node-pre-gyp@1.0.11: - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true - dependencies: - detect-libc: 2.0.2 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.5.4 - tar: 6.2.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - - /@protobufjs/aspromise@1.1.2: - resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - dev: false - - /@protobufjs/base64@1.1.2: - resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - dev: false - - /@protobufjs/codegen@2.0.4: - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} - dev: false - - /@protobufjs/eventemitter@1.1.0: - resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} - dev: false - - /@protobufjs/fetch@1.1.0: - resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/inquire': 1.1.0 - dev: false - - /@protobufjs/float@1.0.2: - resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - dev: false - - /@protobufjs/inquire@1.1.0: - resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} - dev: false - - /@protobufjs/path@1.1.2: - resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - dev: false - - /@protobufjs/pool@1.1.0: - resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - dev: false - - /@protobufjs/utf8@1.1.0: - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - dev: false - - /@sentry-internal/tracing@7.84.0: - resolution: {integrity: sha512-y9bGYA0OM6PEREfd+nk4UURZy29tpIw+7vQwpxWfEVs2fqq0/5TBFX/tKFb8AKUI9lVM8v0bcF0bNSCnuPQZHQ==} - engines: {node: '>=8'} - dependencies: - '@sentry/core': 7.84.0 - '@sentry/types': 7.84.0 - '@sentry/utils': 7.84.0 - dev: false - - /@sentry/core@7.84.0: - resolution: {integrity: sha512-tbuwunbBx2kSex15IHCqHDnrMfIlqPc6w/76fwkGqokz3oh9GSEGlLICwmBWL8AypWimUg13IDtFpD0TJTriWA==} - engines: {node: '>=8'} - dependencies: - '@sentry/types': 7.84.0 - '@sentry/utils': 7.84.0 - dev: false - - /@sentry/node@7.84.0: - resolution: {integrity: sha512-Xm3fIXT3TZOQi+6uQBavI8iOehD3PkY7v0y3hog0d4lQTH88vQK9BBsI+jZEq81Em+RG/u7vZNiFo6YMTnWF7Q==} - engines: {node: '>=8'} - dependencies: - '@sentry-internal/tracing': 7.84.0 - '@sentry/core': 7.84.0 - '@sentry/types': 7.84.0 - '@sentry/utils': 7.84.0 - https-proxy-agent: 5.0.1 - transitivePeerDependencies: - - supports-color - dev: false - - /@sentry/tracing@7.84.0: - resolution: {integrity: sha512-NhBX28vUmCu/5avyGKX6B4UTm4MTOfbdg9ZzCnS7hPuWDfEAUIVHZVryi2q8bqp2DNGJvS9qIq/TSf39JIpdJg==} - engines: {node: '>=8'} - dependencies: - '@sentry-internal/tracing': 7.84.0 - dev: false - - /@sentry/types@7.84.0: - resolution: {integrity: sha512-VqGLIF3JOUrk7yIXjLXJvAORkZL1e3dDX0Q1okRehwyt/5CRE+mdUTeJZkBo9P9mBwgMyvtwklzOGGrzjb4eMA==} - engines: {node: '>=8'} - dev: false - - /@sentry/utils@7.84.0: - resolution: {integrity: sha512-qdUVuxnRBvaf05AU+28R+xYtZmi/Ymf8os3Njq9g4XuA+QEkZLbzmIpRK5W9Ja7vUtjOeg29Xgg43A8znde9LQ==} - engines: {node: '>=8'} - dependencies: - '@sentry/types': 7.84.0 - dev: false - - /@tsconfig/node10@1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true - - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true - - /@types/body-parser@1.19.3: - resolution: {integrity: sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==} - dependencies: - '@types/connect': 3.4.36 - '@types/node': 20.12.3 - dev: true - - /@types/connect@3.4.36: - resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} - dependencies: - '@types/node': 20.12.3 - dev: true - - /@types/express-serve-static-core@4.17.37: - resolution: {integrity: sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==} - dependencies: - '@types/node': 20.12.3 - '@types/qs': 6.9.8 - '@types/range-parser': 1.2.5 - '@types/send': 0.17.2 - dev: true - - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - dependencies: - '@types/body-parser': 1.19.3 - '@types/express-serve-static-core': 4.17.37 - '@types/qs': 6.9.8 - '@types/serve-static': 1.15.3 - dev: true - - /@types/http-errors@2.0.2: - resolution: {integrity: sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==} - dev: true - - /@types/mime@1.3.3: - resolution: {integrity: sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==} - dev: true - - /@types/mime@3.0.2: - resolution: {integrity: sha512-Wj+fqpTLtTbG7c0tH47dkahefpLKEbB+xAZuLq7b4/IDHPl/n6VoXcyUQ2bypFlbSwvCr0y+bD4euTTqTJsPxQ==} - dev: true - - /@types/node@20.12.3: - resolution: {integrity: sha512-sD+ia2ubTeWrOu+YMF+MTAB7E+O7qsMqAbMfW7DG3K1URwhZ5hN1pLlRVGbf4wDFzSfikL05M17EyorS86jShw==} - dependencies: - undici-types: 5.26.5 - - /@types/qs@6.9.8: - resolution: {integrity: sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==} - dev: true - - /@types/range-parser@1.2.5: - resolution: {integrity: sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==} - dev: true - - /@types/send@0.17.2: - resolution: {integrity: sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==} - dependencies: - '@types/mime': 1.3.3 - '@types/node': 20.12.3 - dev: true - - /@types/serve-static@1.15.3: - resolution: {integrity: sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==} - dependencies: - '@types/http-errors': 2.0.2 - '@types/mime': 3.0.2 - '@types/node': 20.12.3 - dev: true - - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: false - - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: false - - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: false - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: false - - /aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: false - - /are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - dev: false - - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: false - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: false - - /body-parser@1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: false - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: false - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: false - - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.2.1 - dev: false - - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - dev: false - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: false - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false - - /color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: false - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: false - - /console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: false - - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - dev: false - - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: false - - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - dev: false - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: false - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: false - - /delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: false - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: false - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: false - - /detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - dev: false - - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: false - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: false - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: false - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: false - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: false - - /express@4.18.2: - resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.1 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.5.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: false - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: false - - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: false - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: false - - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: false - - /gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: false - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: false - - /get-intrinsic@1.2.1: - resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} - dependencies: - function-bind: 1.1.1 - has: 1.0.4 - has-proto: 1.0.1 - has-symbols: 1.0.3 - dev: false - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: false - - /google-protobuf@3.15.8: - resolution: {integrity: sha512-2jtfdqTaSxk0cuBJBtTTWsot4WtR9RVr2rXg7x7OoqiuOKopPrwXpM1G4dXIkLcUNRh3RKzz76C8IOkksZSeOw==} - dev: false - - /google-protobuf@3.21.2: - resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==} - dev: false - - /grpc-tools@1.12.4: - resolution: {integrity: sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==} - hasBin: true - requiresBuild: true - dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - - /grpc_tools_node_protoc_ts@5.3.3: - resolution: {integrity: sha512-M/YrklvVXMtuuj9kb42PxeouZhs7Ul+R4e/31XwrankUcKL8cQQP50Q9q+KEHGyHQaPt6VtKKsxMgLaKbCxeww==} - hasBin: true - dependencies: - google-protobuf: 3.15.8 - handlebars: 4.7.7 - dev: false - - /handlebars@4.7.7: - resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.4 - dev: false - - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: false - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: false - - /has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: false - - /has@1.0.4: - resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} - engines: {node: '>= 0.4.0'} - dev: false - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: false - - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: false - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: false - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false - - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: false - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false - - /lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - dev: false - - /long@5.2.3: - resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} - dev: false - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: false - - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.1 - dev: false - - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: false - - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: false - - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: false - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: false - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: false - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: false - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: false - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: false - - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: false - - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - dev: false - - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - dev: false - - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: false - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: false - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: false - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: false - - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: false - - /node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: false - - /nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - abbrev: 1.1.1 - dev: false - - /npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: false - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: false - - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: false - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: false - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: false - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: false - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: false - - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: false - - /prettier@3.1.0: - resolution: {integrity: sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /protobufjs@7.2.5: - resolution: {integrity: sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==} - engines: {node: '>=12.0.0'} - requiresBuild: true - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/node': 20.12.3 - long: 5.2.3 - dev: false - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: false - - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.4 - dev: false - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: false - - /raw-body@2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: false - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: false - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: false - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: false - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: false - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: false - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: false - - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: false - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: false - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: false - - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: false - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false - - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - object-inspect: 1.12.3 - dev: false - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: false - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: false - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: false - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: false - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: false - - /tar@6.2.0: - resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} - engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: false - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: false - - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: false - - /ts-node@10.9.1(@types/node@20.12.3)(typescript@4.9.5): - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.12.3 - acorn: 8.10.0 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 4.9.5 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - - /ts-protoc-gen@0.15.0: - resolution: {integrity: sha512-TycnzEyrdVDlATJ3bWFTtra3SCiEP0W0vySXReAuEygXCUr1j2uaVyL0DhzjwuUdQoW5oXPwk6oZWeA0955V+g==} - hasBin: true - dependencies: - google-protobuf: 3.21.2 - dev: false - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: false - - /typescript@4.9.5: - resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} - engines: {node: '>=4.2.0'} - hasBin: true - dev: true - - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: false - optional: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: false - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false - - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - dev: false - - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: false - - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: false - - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: false - - /wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - dependencies: - string-width: 4.2.3 - dev: false - - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: false - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: false - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: false - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: false - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: false - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: false - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: false - - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true diff --git a/server_old/server.ts b/server_old/server.ts deleted file mode 100644 index 1c09ff768..000000000 --- a/server_old/server.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as Sentry from '@sentry/node'; -import * as Tracing from '@sentry/tracing'; - -import app from './src/app'; - -// initializing sentry -Sentry.init({ - dsn: process.env.SENTRY_INGEST_SERVER, - integrations: [ - // enable HTTP calls tracing - new Sentry.Integrations.Http({ tracing: true }), - // enable Express.js middleware tracing - new Tracing.Integrations.Express({ app }), - ], - tracesSampleRate: Number(process.env.SENTRY_TRACE_RATE_SERVER), -}); - -const server = app.listen(app.get('port'), () => { - console.log('App is running at http://localhost:%d in %s mode', app.get('port'), app.get('env')); - console.log('Press CTRL-C to stop\n'); -}); - -export default server; diff --git a/server_old/src/app.ts b/server_old/src/app.ts deleted file mode 100644 index dce417b6f..000000000 --- a/server_old/src/app.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as express from 'express'; -import { Response, Request } from 'express'; -import * as bodyParser from 'body-parser'; -import * as indexController from './index'; -import { getAuto } from './controllers/index'; - -const app = express(); - -app.set('port', process.env.PORT || 3001); - -// parse application/x-www-form-urlencoded -app.use(bodyParser.urlencoded({ extended: true })); -// parse application/json -app.use(bodyParser.json()); - -app.use((req: Request, res: Response, next) => { - res.header('Access-Control-Allow-Origin', '*'); // update to match the domain you will make the request from - res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); - next(); -}); - -app.get('/', indexController.index); -app.post('/auto', getAuto); - -export default app; diff --git a/server_old/src/controllers/index.ts b/server_old/src/controllers/index.ts deleted file mode 100644 index 11a80640d..000000000 --- a/server_old/src/controllers/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { getAuto } from './getAutotimetable'; - -export { getAuto }; diff --git a/server_old/src/index.ts b/server_old/src/index.ts deleted file mode 100644 index 3b601b438..000000000 --- a/server_old/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Request, Response } from 'express'; - -export let index = (req: Request, res: Response) => { - res.send('Hello Notangles!'); -}; diff --git a/server_old/tsconfig.json b/server_old/tsconfig.json deleted file mode 100644 index 99e22acbb..000000000 --- a/server_old/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "compilerOptions": { - "types": ["node"], - "resolveJsonModule": true, - "outDir": "./dist" - } -} From 5c53bc6be09d69583d09700eb37dff8531543628 Mon Sep 17 00:00:00 2001 From: ray Date: Fri, 10 May 2024 21:06:46 +1000 Subject: [PATCH 16/92] added nestjs support with auto timetabling --- client/src/api/getAutoTimetable.ts | 1 - client/src/components/controls/Autotimetabler.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/client/src/api/getAutoTimetable.ts b/client/src/api/getAutoTimetable.ts index f343a2fb7..4ee00a09e 100644 --- a/client/src/api/getAutoTimetable.ts +++ b/client/src/api/getAutoTimetable.ts @@ -2,7 +2,6 @@ import NetworkError from '../interfaces/NetworkError'; import { API_URL } from './config'; const getAutoTimetable = async (data: any): Promise<[number[], boolean]> => { - console.log(`${API_URL.auto}`); try { const res = await fetch(`${API_URL.auto}`, { method: 'POST', diff --git a/client/src/components/controls/Autotimetabler.tsx b/client/src/components/controls/Autotimetabler.tsx index 543a2a028..857980425 100644 --- a/client/src/components/controls/Autotimetabler.tsx +++ b/client/src/components/controls/Autotimetabler.tsx @@ -192,7 +192,6 @@ const Autotimetabler: React.FC = ({ handleSelectClass }) => ]; try { - console.log(timetableData); const [resultsWithEvents, isOptimal] = await getAutoTimetable(timetableData); const results = resultsWithEvents.slice(0, targetActivities.current.length); From ae0e8c713e74d9fe5b2a18b2fbb49eca8eaf24ac Mon Sep 17 00:00:00 2001 From: ray Date: Fri, 10 May 2024 22:11:09 +1000 Subject: [PATCH 17/92] removing controller test files for main app --- server/src/app.controller.spec.ts | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 server/src/app.controller.spec.ts diff --git a/server/src/app.controller.spec.ts b/server/src/app.controller.spec.ts deleted file mode 100644 index d22f3890a..000000000 --- a/server/src/app.controller.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); - - describe('root', () => { - it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!'); - }); - }); -}); From 0a926a773a27e9b902c6ef374b730afe67293512 Mon Sep 17 00:00:00 2001 From: ray Date: Fri, 10 May 2024 22:13:13 +1000 Subject: [PATCH 18/92] testing out no frozen lockfile for docker image --- server/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/Dockerfile b/server/Dockerfile index fed6c4259..c0921ef7a 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -5,7 +5,7 @@ RUN pnpm install @nestjs/cli WORKDIR /server COPY package.json pnpm-lock.yaml ./ -RUN pnpm i --frozen-lockfile +RUN pnpm i --no-frozen-lockfile COPY . . RUN pnpm run build From f6c15dd5df01f926f8cc4ae1a21b6424a17a8f9d Mon Sep 17 00:00:00 2001 From: Raiyan Ahmed <80839724+Rayahhhmed@users.noreply.github.com> Date: Fri, 10 May 2024 22:14:48 +1000 Subject: [PATCH 19/92] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c257fba3..a46137791 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: restore-keys: | ${{ runner.os }}-pnpm-store- - name: Install dependencies - run: pnpm install --frozen-lockfile + run: pnpm install --no-frozen-lockfile working-directory: ${{ matrix.component }} - name: Build run: pnpm run build From 9af7d36434938a27789f0d84277beb45c09ad214 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 11 May 2024 20:57:17 +1000 Subject: [PATCH 20/92] added the old endpoints: Auth user, prisma and user as well as the protobuf auto endpoints --- server/package.json | 7 + server/pnpm-lock.yaml | 197 ++++++++++++++++++-- server/src/app.module.ts | 17 +- server/src/auth/auth.controller.spec.ts | 18 ++ server/src/auth/auth.controller.ts | 35 ++++ server/src/auth/auth.module.ts | 24 +++ server/src/auth/auth.service.spec.ts | 18 ++ server/src/auth/auth.service.ts | 34 ++++ server/src/auth/authenticated.guard.ts | 9 + server/src/auth/dtos/auth.dto.ts | 7 + server/src/auth/dtos/index.ts | 1 + server/src/auth/login.guard.ts | 12 ++ server/src/auth/oidc.strategy.ts | 62 ++++++ server/src/auth/session.serializer.ts | 14 ++ server/src/config.ts | 2 + server/src/friend/dto/friend.dto.ts | 17 ++ server/src/friend/dto/index.ts | 1 + server/src/friend/friend.controller.spec.ts | 18 ++ server/src/friend/friend.controller.ts | 40 ++++ server/src/friend/friend.module.ts | 9 + server/src/friend/friend.service.spec.ts | 18 ++ server/src/friend/friend.service.ts | 24 +++ server/src/main.ts | 32 +++- server/src/prisma/prisma.module.ts | 7 + server/src/prisma/prisma.service.ts | 17 ++ server/src/user/dto/index.ts | 3 + server/src/user/dto/settings.dto.ts | 14 ++ server/src/user/dto/timetable.dto.ts | 21 +++ server/src/user/dto/user.dto.ts | 45 +++++ server/src/user/user.controller.spec.ts | 18 ++ server/src/user/user.controller.ts | 53 ++++++ server/src/user/user.module.ts | 9 + server/src/user/user.service.spec.ts | 18 ++ server/src/user/user.service.ts | 86 +++++++++ 34 files changed, 892 insertions(+), 15 deletions(-) create mode 100644 server/src/auth/auth.controller.spec.ts create mode 100644 server/src/auth/auth.controller.ts create mode 100644 server/src/auth/auth.module.ts create mode 100644 server/src/auth/auth.service.spec.ts create mode 100644 server/src/auth/auth.service.ts create mode 100644 server/src/auth/authenticated.guard.ts create mode 100644 server/src/auth/dtos/auth.dto.ts create mode 100644 server/src/auth/dtos/index.ts create mode 100644 server/src/auth/login.guard.ts create mode 100644 server/src/auth/oidc.strategy.ts create mode 100644 server/src/auth/session.serializer.ts create mode 100644 server/src/friend/dto/friend.dto.ts create mode 100644 server/src/friend/dto/index.ts create mode 100644 server/src/friend/friend.controller.spec.ts create mode 100644 server/src/friend/friend.controller.ts create mode 100644 server/src/friend/friend.module.ts create mode 100644 server/src/friend/friend.service.spec.ts create mode 100644 server/src/friend/friend.service.ts create mode 100644 server/src/prisma/prisma.module.ts create mode 100644 server/src/prisma/prisma.service.ts create mode 100644 server/src/user/dto/index.ts create mode 100644 server/src/user/dto/settings.dto.ts create mode 100644 server/src/user/dto/timetable.dto.ts create mode 100644 server/src/user/dto/user.dto.ts create mode 100644 server/src/user/user.controller.spec.ts create mode 100644 server/src/user/user.controller.ts create mode 100644 server/src/user/user.module.ts create mode 100644 server/src/user/user.service.spec.ts create mode 100644 server/src/user/user.service.ts diff --git a/server/package.json b/server/package.json index deffa6f6a..0d470cb60 100644 --- a/server/package.json +++ b/server/package.json @@ -22,13 +22,20 @@ "dependencies": { "@grpc/grpc-js": "^1.10.7", "@nestjs/common": "^10.0.0", + "@nestjs/config": "^3.2.2", "@nestjs/core": "^10.0.0", "@nestjs/mapped-types": "*", + "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^10.0.0", "@prisma/client": "5.13.0", + "@quixo3/prisma-session-store": "^3.1.13", + "class-transformer": "^0.5.1", "class-validator": "^0.14.1", + "express-session": "^1.18.0", "google-protobuf": "^3.21.2", "grpc_tools_node_protoc_ts": "^5.3.3", + "openid-client": "^5.6.5", + "passport": "^0.7.0", "protobufjs": "4.1.3", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index ecfb713a7..9e4192a12 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -10,28 +10,49 @@ dependencies: version: 1.10.7 '@nestjs/common': specifier: ^10.0.0 - version: 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + version: 10.3.8(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/config': + specifier: ^3.2.2 + version: 3.2.2(@nestjs/common@10.3.8)(rxjs@7.8.1) '@nestjs/core': specifier: ^10.0.0 version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/mapped-types': specifier: '*' - version: 2.0.5(@nestjs/common@10.3.8)(class-validator@0.14.1)(reflect-metadata@0.2.2) + version: 2.0.5(@nestjs/common@10.3.8)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2) + '@nestjs/passport': + specifier: ^10.0.3 + version: 10.0.3(@nestjs/common@10.3.8)(passport@0.7.0) '@nestjs/platform-express': specifier: ^10.0.0 version: 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) '@prisma/client': specifier: 5.13.0 version: 5.13.0(prisma@5.13.0) + '@quixo3/prisma-session-store': + specifier: ^3.1.13 + version: 3.1.13(@prisma/client@5.13.0)(express-session@1.18.0) + class-transformer: + specifier: ^0.5.1 + version: 0.5.1 class-validator: specifier: ^0.14.1 version: 0.14.1 + express-session: + specifier: ^1.18.0 + version: 1.18.0 google-protobuf: specifier: ^3.21.2 version: 3.21.2 grpc_tools_node_protoc_ts: specifier: ^5.3.3 version: 5.3.3 + openid-client: + specifier: ^5.6.5 + version: 5.6.5 + passport: + specifier: ^0.7.0 + version: 0.7.0 protobufjs: specifier: 4.1.3 version: 4.1.3 @@ -931,7 +952,7 @@ packages: - webpack-cli dev: true - /@nestjs/common@10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1): + /@nestjs/common@10.3.8(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1): resolution: {integrity: sha512-P+vPEIvqx2e+fonsYVlFXKvoChyJ8Tq+lfpqdVFqblovHbFr3kZ/nYX0cPs+XuW6bnRT8tz0SSR9XBGU43kJhw==} peerDependencies: class-transformer: '*' @@ -944,6 +965,7 @@ packages: class-validator: optional: true dependencies: + class-transformer: 0.5.1 class-validator: 0.14.1 iterare: 1.2.1 reflect-metadata: 0.2.2 @@ -951,6 +973,20 @@ packages: tslib: 2.6.2 uid: 2.0.2 + /@nestjs/config@3.2.2(@nestjs/common@10.3.8)(rxjs@7.8.1): + resolution: {integrity: sha512-vGICPOui5vE6kPz1iwQ7oCnp3qWgqxldPmBQ9onkVoKlBtyc83KJCr7CjuVtf4OdovMAVcux1d8Q6jglU2ZphA==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + rxjs: ^7.1.0 + dependencies: + '@nestjs/common': 10.3.8(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + dotenv: 16.4.5 + dotenv-expand: 10.0.0 + lodash: 4.17.21 + rxjs: 7.8.1 + uuid: 9.0.1 + dev: false + /@nestjs/core@10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1): resolution: {integrity: sha512-AxF4tpYLDNn5Wfb3C4bNaaHJ4pREH5FJrSisR2A5zkYpQFORFs0Tc36lOFPMwBTy8Iv2wUwWLUVc5ftBnxEv4w==} requiresBuild: true @@ -969,7 +1005,7 @@ packages: '@nestjs/websockets': optional: true dependencies: - '@nestjs/common': 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.8(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) '@nuxtjs/opencollective': 0.3.2 fast-safe-stringify: 2.1.1 @@ -982,7 +1018,7 @@ packages: transitivePeerDependencies: - encoding - /@nestjs/mapped-types@2.0.5(@nestjs/common@10.3.8)(class-validator@0.14.1)(reflect-metadata@0.2.2): + /@nestjs/mapped-types@2.0.5(@nestjs/common@10.3.8)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2): resolution: {integrity: sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==} peerDependencies: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 @@ -995,18 +1031,29 @@ packages: class-validator: optional: true dependencies: - '@nestjs/common': 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.8(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + class-transformer: 0.5.1 class-validator: 0.14.1 reflect-metadata: 0.2.2 dev: false + /@nestjs/passport@10.0.3(@nestjs/common@10.3.8)(passport@0.7.0): + resolution: {integrity: sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + passport: ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 + dependencies: + '@nestjs/common': 10.3.8(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + passport: 0.7.0 + dev: false + /@nestjs/platform-express@10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8): resolution: {integrity: sha512-sifLoxgEJvAgbim1UuW6wyScMfkS9SVQRH+lN33N/9ZvZSjO6NSDLOe+wxqsnZkia+QrjFC0qy0ITRAsggfqbg==} peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/core': ^10.0.0 dependencies: - '@nestjs/common': 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.8(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) body-parser: 1.20.2 cors: 2.8.5 @@ -1059,12 +1106,17 @@ packages: '@nestjs/platform-express': optional: true dependencies: - '@nestjs/common': 10.3.8(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.8(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8)(@nestjs/core@10.3.8) tslib: 2.6.2 dev: true + /@noble/hashes@1.4.0: + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1097,6 +1149,12 @@ packages: transitivePeerDependencies: - encoding + /@paralleldrive/cuid2@2.2.2: + resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} + dependencies: + '@noble/hashes': 1.4.0 + dev: false + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1192,6 +1250,20 @@ packages: resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} dev: false + /@quixo3/prisma-session-store@3.1.13(@prisma/client@5.13.0)(express-session@1.18.0): + resolution: {integrity: sha512-EAuOvYAaAsQ0OqxkdJG/Qs3cxlT4VV8SFHjtsA3G01uB1b6r7xftX3oeg7mcG0HN/DI1qOqwvy3YFoJ38ls0iA==} + engines: {node: '>=12.0'} + peerDependencies: + '@prisma/client': '>=2.16.1' + express-session: '>=1.17.1' + dependencies: + '@paralleldrive/cuid2': 2.2.2 + '@prisma/client': 5.13.0(prisma@5.13.0) + express-session: 1.18.0 + ts-dedent: 2.2.0 + type-fest: 2.19.0 + dev: false + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -2117,6 +2189,9 @@ packages: resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} dev: true + /class-transformer@0.5.1: + resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} + /class-validator@0.14.1: resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==} dependencies: @@ -2277,6 +2352,10 @@ packages: /cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + /cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + dev: false + /cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} @@ -2451,6 +2530,16 @@ packages: esutils: 2.0.3 dev: true + /dotenv-expand@10.0.0: + resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} + engines: {node: '>=12'} + dev: false + + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + dev: false + /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true @@ -2715,6 +2804,22 @@ packages: jest-util: 29.7.0 dev: true + /express-session@1.18.0: + resolution: {integrity: sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==} + engines: {node: '>= 0.8.0'} + dependencies: + cookie: 0.6.0 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + on-headers: 1.0.2 + parseurl: 1.3.3 + safe-buffer: 5.2.1 + uid-safe: 2.1.5 + transitivePeerDependencies: + - supports-color + dev: false + /express@4.19.2: resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} engines: {node: '>= 0.10.0'} @@ -3850,6 +3955,10 @@ packages: - ts-node dev: true + /jose@4.15.5: + resolution: {integrity: sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==} + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true @@ -3988,7 +4097,6 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true /log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} @@ -4023,7 +4131,6 @@ packages: engines: {node: '>=10'} dependencies: yallist: 4.0.0 - dev: true /magic-string@0.30.5: resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} @@ -4247,15 +4354,30 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + /object-hash@2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + dev: false + /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + /oidc-token-hash@5.0.3: + resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} + engines: {node: ^10.13.0 || >=12.0.0} + dev: false + /on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} dependencies: ee-first: 1.1.1 + /on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + dev: false + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -4268,6 +4390,15 @@ packages: mimic-fn: 2.1.0 dev: true + /openid-client@5.6.5: + resolution: {integrity: sha512-5P4qO9nGJzB5PI0LFlhj4Dzg3m4odt0qsJTfyEtZyOlkgpILwEioOhVVJOrS1iVH494S4Ee5OCjjg6Bf5WOj3w==} + dependencies: + jose: 4.15.5 + lru-cache: 6.0.0 + object-hash: 2.2.0 + oidc-token-hash: 5.0.3 + dev: false + /optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -4365,6 +4496,20 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + /passport-strategy@1.0.0: + resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==} + engines: {node: '>= 0.4.0'} + dev: false + + /passport@0.7.0: + resolution: {integrity: sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==} + engines: {node: '>= 0.4.0'} + dependencies: + passport-strategy: 1.0.0 + pause: 0.0.1 + utils-merge: 1.0.1 + dev: false + /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -4402,6 +4547,10 @@ packages: engines: {node: '>=8'} dev: true + /pause@0.0.1: + resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==} + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true @@ -4542,6 +4691,11 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true + /random-bytes@1.0.0: + resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==} + engines: {node: '>= 0.8'} + dev: false + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -5146,6 +5300,11 @@ packages: typescript: 5.4.5 dev: true + /ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + dev: false + /ts-jest@29.1.2(@babel/core@7.24.5)(jest@29.7.0)(typescript@5.4.5): resolution: {integrity: sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==} engines: {node: ^16.10.0 || ^18.0.0 || >=20.0.0} @@ -5277,6 +5436,11 @@ packages: engines: {node: '>=10'} dev: true + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: false + /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -5307,6 +5471,13 @@ packages: dev: false optional: true + /uid-safe@2.1.5: + resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} + engines: {node: '>= 0.8'} + dependencies: + random-bytes: 1.0.0 + dev: false + /uid@2.0.2: resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} engines: {node: '>=8'} @@ -5349,6 +5520,11 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true @@ -5575,7 +5751,6 @@ packages: /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} diff --git a/server/src/app.module.ts b/server/src/app.module.ts index acf0dfcab..b7b64ee07 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -1,10 +1,21 @@ +import { AutoModule } from './auto/auto.module'; import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; -import { AutoModule } from './auto/auto.module'; - +import { PrismaModule } from './prisma/prisma.module'; +import { AuthModule } from './auth/auth.module'; +import { UserModule } from './user/user.module'; +import { FriendModule } from './friend/friend.module'; +import { ConfigModule } from '@nestjs/config'; @Module({ - imports: [AutoModule], + imports: [ + ConfigModule.forRoot(), + AuthModule, + AutoModule, + UserModule, + FriendModule, + PrismaModule, + ], controllers: [AppController], providers: [AppService], }) diff --git a/server/src/auth/auth.controller.spec.ts b/server/src/auth/auth.controller.spec.ts new file mode 100644 index 000000000..27a31e618 --- /dev/null +++ b/server/src/auth/auth.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AuthController } from './auth.controller'; + +describe('AuthController', () => { + let controller: AuthController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [AuthController], + }).compile(); + + controller = module.get(AuthController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/server/src/auth/auth.controller.ts b/server/src/auth/auth.controller.ts new file mode 100644 index 000000000..3dfcbd2fd --- /dev/null +++ b/server/src/auth/auth.controller.ts @@ -0,0 +1,35 @@ +import { Controller, Get, Request, Res, UseGuards } from '@nestjs/common'; +import { Response } from 'express'; + +import { REDIRECT_LINK } from '../config'; +import { AuthService } from './auth.service'; +import { LoginGuard } from './login.guard'; + +@Controller('auth') +export class AuthController { + constructor(private authService: AuthService) {} + + @UseGuards(LoginGuard) + @Get('/login') + login() {} + + @Get('/user') + user(@Request() req, @Res() res: Response) { + if (req.user) { + return res.json(req.user.userinfo.sub); + } + + return res.json(req.user); + } + + @UseGuards(LoginGuard) + @Get('/callback/csesoc') + loginCallback(@Res() res: Response) { + res.redirect(REDIRECT_LINK); + } + + @Get('/logout') + async logout(@Request() req, @Res() res: Response) { + this.authService.logout(req, res); + } +} diff --git a/server/src/auth/auth.module.ts b/server/src/auth/auth.module.ts new file mode 100644 index 000000000..f491cef48 --- /dev/null +++ b/server/src/auth/auth.module.ts @@ -0,0 +1,24 @@ +import { Module } from '@nestjs/common'; +import { PassportModule } from '@nestjs/passport'; +import { OidcStrategy, buildOpenIdClient } from './oidc.strategy'; +import { SessionSerializer } from './session.serializer'; +import { AuthService } from './auth.service'; +import { AuthController } from './auth.controller'; + +const OidcStrategyFactory = { + provide: 'OidcStrategy', + useFactory: async (authService: AuthService) => { + const client = await buildOpenIdClient(); + return new OidcStrategy(authService, client); + }, + inject: [AuthService], +}; + +@Module({ + imports: [ + PassportModule.register({ session: true, defaultStrategy: 'oidc' }), + ], + controllers: [AuthController], + providers: [OidcStrategyFactory, SessionSerializer, AuthService], +}) +export class AuthModule {} diff --git a/server/src/auth/auth.service.spec.ts b/server/src/auth/auth.service.spec.ts new file mode 100644 index 000000000..800ab6626 --- /dev/null +++ b/server/src/auth/auth.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AuthService } from './auth.service'; + +describe('AuthService', () => { + let service: AuthService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [AuthService], + }).compile(); + + service = module.get(AuthService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/auth/auth.service.ts b/server/src/auth/auth.service.ts new file mode 100644 index 000000000..e6c76de4c --- /dev/null +++ b/server/src/auth/auth.service.ts @@ -0,0 +1,34 @@ +import { Injectable, Request, Res } from '@nestjs/common'; +import { Response } from 'express'; +import { Issuer } from 'openid-client'; +import { REDIRECT_LINK } from '../config'; + +@Injectable() +export class AuthService { + async logout(@Request() req, @Res() res: Response): Promise { + const id_token = req.user ? req.user.id_token : undefined; + + const TrustIssuer = await Issuer.discover( + `${process.env.OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER}/.well-known/openid-configuration`, + ); + + if (!id_token || !TrustIssuer) { + return res.redirect(REDIRECT_LINK); + } + + req.logout((err) => { + req.session.destroy(async (error: any) => { + const end_session_endpoint = TrustIssuer.metadata.end_session_endpoint; + if (end_session_endpoint) { + res.redirect( + end_session_endpoint + + '?post_logout_redirect_uri=' + + process.env + .OAUTH2_CLIENT_REGISTRATION_LOGIN_POST_LOGOUT_REDIRECT_URI + + (id_token ? '&id_token_hint=' + id_token : ''), + ); + } + }); + }); + } +} diff --git a/server/src/auth/authenticated.guard.ts b/server/src/auth/authenticated.guard.ts new file mode 100644 index 000000000..0d9bd6bc6 --- /dev/null +++ b/server/src/auth/authenticated.guard.ts @@ -0,0 +1,9 @@ +import { ExecutionContext, Injectable, CanActivate } from '@nestjs/common'; + +@Injectable() +export class AuthenticatedGuard implements CanActivate { + async canActivate(context: ExecutionContext) { + const request = context.switchToHttp().getRequest(); + return request.isAuthenticated(); + } +} diff --git a/server/src/auth/dtos/auth.dto.ts b/server/src/auth/dtos/auth.dto.ts new file mode 100644 index 000000000..fb4ce9096 --- /dev/null +++ b/server/src/auth/dtos/auth.dto.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty, IsString } from 'class-validator'; + +export class AuthDto { + @IsString() @IsNotEmpty() code: string; + + @IsString() @IsNotEmpty() state: string; +} diff --git a/server/src/auth/dtos/index.ts b/server/src/auth/dtos/index.ts new file mode 100644 index 000000000..0ee0429bc --- /dev/null +++ b/server/src/auth/dtos/index.ts @@ -0,0 +1 @@ +export * from './auth.dto'; diff --git a/server/src/auth/login.guard.ts b/server/src/auth/login.guard.ts new file mode 100644 index 000000000..c16b6042b --- /dev/null +++ b/server/src/auth/login.guard.ts @@ -0,0 +1,12 @@ +import { ExecutionContext, Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; + +@Injectable() +export class LoginGuard extends AuthGuard('oidc') { + async canActivate(context: ExecutionContext) { + const result = (await super.canActivate(context)) as boolean; + const request = context.switchToHttp().getRequest(); + await super.logIn(request); + return result; + } +} diff --git a/server/src/auth/oidc.strategy.ts b/server/src/auth/oidc.strategy.ts new file mode 100644 index 000000000..5327b90e6 --- /dev/null +++ b/server/src/auth/oidc.strategy.ts @@ -0,0 +1,62 @@ +import { UnauthorizedException } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; +import { + Strategy, + Client, + UserinfoResponse, + TokenSet, + Issuer, +} from 'openid-client'; +import { AuthService } from './auth.service'; + +export const buildOpenIdClient = async () => { + const TrustIssuer = await Issuer.discover( + `${process.env.OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER}/.well-known/openid-configuration`, + ); + const client = new TrustIssuer.Client({ + client_id: process.env.OAUTH2_CLIENT_REGISTRATION_LOGIN_CLIENT_ID, + client_secret: process.env.OAUTH2_CLIENT_REGISTRATION_LOGIN_CLIENT_SECRET, + }); + return client; +}; + +export class OidcStrategy extends PassportStrategy(Strategy, 'oidc') { + client: Client; + + constructor( + private readonly authService: AuthService, + client: Client, + ) { + super({ + client: client, + params: { + redirect_uris: + process.env.OAUTH2_CLIENT_REGISTRATION_LOGIN_REDIRECT_URI, + scope: process.env.OAUTH2_CLIENT_REGISTRATION_LOGIN_SCOPE, + }, + passReqToCallback: false, + usePKCE: false, + }); + + this.client = client; + } + + async validate(tokenset: TokenSet): Promise { + const userinfo: UserinfoResponse = await this.client.userinfo(tokenset); + try { + console.log(tokenset); + const id_token = tokenset.id_token; + const access_token = tokenset.access_token; + const refresh_token = tokenset.refresh_token; + const user = { + id_token, + access_token, + refresh_token, + userinfo, + }; + return user; + } catch (err) { + throw new UnauthorizedException(); + } + } +} diff --git a/server/src/auth/session.serializer.ts b/server/src/auth/session.serializer.ts new file mode 100644 index 000000000..664f77777 --- /dev/null +++ b/server/src/auth/session.serializer.ts @@ -0,0 +1,14 @@ +import { PassportSerializer } from '@nestjs/passport'; +import { Injectable } from '@nestjs/common'; +@Injectable() +export class SessionSerializer extends PassportSerializer { + serializeUser(user: any, done: (err: Error, user: any) => void): any { + done(null, user); + } + deserializeUser( + payload: any, + done: (err: Error, payload: string) => void, + ): any { + done(null, payload); + } +} diff --git a/server/src/config.ts b/server/src/config.ts index cd3f54eb9..89e4e28e7 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -16,3 +16,5 @@ export const API_CONFIG: Record = { }, }; export const config: Config = API_CONFIG[process.env.NODE_ENV || Env.DEV]; + +export const REDIRECT_LINK = 'http://localhost:5173'; diff --git a/server/src/friend/dto/friend.dto.ts b/server/src/friend/dto/friend.dto.ts new file mode 100644 index 000000000..ce9bb69b8 --- /dev/null +++ b/server/src/friend/dto/friend.dto.ts @@ -0,0 +1,17 @@ +import { IsNotEmpty, IsString } from 'class-validator'; + +export class friendDto { + @IsString() + @IsNotEmpty() + senderId: string; + + @IsString() + @IsNotEmpty() + sendeeId: string; +} + +export class friendRequestDto { + @IsString() + @IsNotEmpty() + requestId: string; +} diff --git a/server/src/friend/dto/index.ts b/server/src/friend/dto/index.ts new file mode 100644 index 000000000..1392bb23e --- /dev/null +++ b/server/src/friend/dto/index.ts @@ -0,0 +1 @@ +export * from './friend.dto'; diff --git a/server/src/friend/friend.controller.spec.ts b/server/src/friend/friend.controller.spec.ts new file mode 100644 index 000000000..33542ffe8 --- /dev/null +++ b/server/src/friend/friend.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { FriendController } from './friend.controller'; + +describe('FriendController', () => { + let controller: FriendController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [FriendController], + }).compile(); + + controller = module.get(FriendController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/server/src/friend/friend.controller.ts b/server/src/friend/friend.controller.ts new file mode 100644 index 000000000..81b4cdf69 --- /dev/null +++ b/server/src/friend/friend.controller.ts @@ -0,0 +1,40 @@ +import { Body, Controller, Delete, Get, Param, Post } from '@nestjs/common'; +import { friendDto, friendRequestDto } from './dto'; +import { FriendService } from './friend.service'; +@Controller('friend') +export class FriendController { + constructor(private friendService: FriendService) {} + @Get(':userId') + findAllFriends(@Param('userId') userId: string) { + return this.friendService.findAllFriends(userId); + } + + @Post() + friendUsers(@Body() friendDto: friendDto) { + return this.friendService.friendUsers( + friendDto.senderId, + friendDto.sendeeId, + ); + } + + @Delete() + unfriendUsers(@Body() friendDTO: friendDto) { + return this.friendService.unfriendUsers( + friendDTO.senderId, + friendDTO.sendeeId, + ); + } + + @Post('request') + sendFriendRequest(@Body() friendDTO: friendDto) { + return this.friendService.sendFriendRequest( + friendDTO.senderId, + friendDTO.sendeeId, + ); + } + + @Delete('request') + deleteFriendRequest(@Body() friendRequestDto: friendRequestDto) { + return this.friendService.deleteFriendRequest(friendRequestDto.requestId); + } +} diff --git a/server/src/friend/friend.module.ts b/server/src/friend/friend.module.ts new file mode 100644 index 000000000..2e5aa94fd --- /dev/null +++ b/server/src/friend/friend.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { FriendService } from './friend.service'; +import { FriendController } from './friend.controller'; + +@Module({ + providers: [FriendService], + controllers: [FriendController], +}) +export class FriendModule {} diff --git a/server/src/friend/friend.service.spec.ts b/server/src/friend/friend.service.spec.ts new file mode 100644 index 000000000..7ed4fd654 --- /dev/null +++ b/server/src/friend/friend.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { FriendService } from './friend.service'; + +describe('FriendService', () => { + let service: FriendService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [FriendService], + }).compile(); + + service = module.get(FriendService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/friend/friend.service.ts b/server/src/friend/friend.service.ts new file mode 100644 index 000000000..c3e3ed6c0 --- /dev/null +++ b/server/src/friend/friend.service.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable({}) +export class FriendService { + findAllFriends(userId: string) { + return { friends: 'none tbh.' }; + } + + friendUsers(senderId: string, sendeeId: string) { + return { senderId, sendeeId }; + } + + unfriendUsers(senderId: string, sendeeId: string) { + return { senderId, sendeeId }; + } + + sendFriendRequest(senderId: string, sendeeId: string) { + return { senderId, sendeeId }; + } + + deleteFriendRequest(requestId: string) { + return { requestId }; + } +} diff --git a/server/src/main.ts b/server/src/main.ts index 86c7a896b..197ed5d37 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,12 +1,42 @@ +import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; +import { PrismaSessionStore } from '@quixo3/prisma-session-store'; +import * as session from 'express-session'; +import * as passport from 'passport'; import { AppModule } from './app.module'; +const { PrismaClient } = require('@prisma/client'); // pnpm breaks in production if require is not used. async function bootstrap() { const app = await NestFactory.create(AppModule); + app.setGlobalPrefix('api'); app.enableCors({ origin: 'http://localhost:5173', // Replace this in production. credentials: true, // Allow credentials (e.g., cookies) to be sent with the request }); - await app.listen(3001); + app.useGlobalPipes(new ValidationPipe()); + app.use( + session({ + store: new PrismaSessionStore(new PrismaClient(), { + checkPeriod: 2 * 60 * 1000, //ms + dbRecordIdIsSessionId: true, + dbRecordIdFunction: undefined, + }), // where session will be stored + secret: process.env.SESSION_SECRET, // to sign session id + resave: false, + saveUninitialized: false, + + rolling: true, // keep session alive + cookie: { + secure: false, + maxAge: 30 * 60 * 1000, // session expires in 1hr, refreshed by `rolling: true` option. + httpOnly: true, // so that cookie can't be accessed via client-side script + }, + }), + ); + app.use(passport.initialize()); + app.use(passport.session()); + + await app.listen(3001); // reminder to change it back to 3001 } + bootstrap(); diff --git a/server/src/prisma/prisma.module.ts b/server/src/prisma/prisma.module.ts new file mode 100644 index 000000000..f9deb7f60 --- /dev/null +++ b/server/src/prisma/prisma.module.ts @@ -0,0 +1,7 @@ +import { Module } from '@nestjs/common'; +import { PrismaService } from './prisma.service'; + +@Module({ + providers: [PrismaService], +}) +export class PrismaModule {} diff --git a/server/src/prisma/prisma.service.ts b/server/src/prisma/prisma.service.ts new file mode 100644 index 000000000..e576e1326 --- /dev/null +++ b/server/src/prisma/prisma.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +// import { PrismaClient } from '@prisma/client'; +const { PrismaClient } = require('@prisma/client'); +import 'dotenv/config'; + +@Injectable() +export class PrismaService extends PrismaClient { + constructor() { + super({ + datasources: { + db: { + url: process.env.DATABASE_URL, + }, + }, + }); + } +} diff --git a/server/src/user/dto/index.ts b/server/src/user/dto/index.ts new file mode 100644 index 000000000..db9f6913c --- /dev/null +++ b/server/src/user/dto/index.ts @@ -0,0 +1,3 @@ +export * from './settings.dto'; +export * from './user.dto'; +export * from './timetable.dto'; diff --git a/server/src/user/dto/settings.dto.ts b/server/src/user/dto/settings.dto.ts new file mode 100644 index 000000000..9c25d9cd8 --- /dev/null +++ b/server/src/user/dto/settings.dto.ts @@ -0,0 +1,14 @@ +import { IsBoolean } from 'class-validator'; + +export class SettingsDto { + @IsBoolean() is12HourMode: boolean; + @IsBoolean() isDarkMode: boolean; + @IsBoolean() isSquareEdges: boolean; + @IsBoolean() isHideFullClasses: boolean; + @IsBoolean() isDefaultUnscheduled: boolean; + @IsBoolean() isHideClassInfo: boolean; + @IsBoolean() isSortAlphabetic: boolean; + @IsBoolean() isShowOnlyOpenClasses: boolean; + @IsBoolean() isHideExamClasses: boolean; + @IsBoolean() isConvertToLocalTimezone: boolean; +} diff --git a/server/src/user/dto/timetable.dto.ts b/server/src/user/dto/timetable.dto.ts new file mode 100644 index 000000000..cde6c9966 --- /dev/null +++ b/server/src/user/dto/timetable.dto.ts @@ -0,0 +1,21 @@ +import { IsArray, IsNotEmpty, IsString, ValidateNested } from 'class-validator'; +import { Type } from 'class-transformer'; + +export class TimetableDto { + @IsString() + timetableId: string; // Randomly generated on the backend + + @IsArray() + @IsString({ each: true }) + selectedCourses: string[]; + + events: EventDto[]; +} + +export class EventDto { + id: string; // Frontend generated event id + name: string; + location: string; + description: string; + colour: string; +} diff --git a/server/src/user/dto/user.dto.ts b/server/src/user/dto/user.dto.ts new file mode 100644 index 000000000..99a5e3db8 --- /dev/null +++ b/server/src/user/dto/user.dto.ts @@ -0,0 +1,45 @@ +import { + IsString, + IsEmail, + IsBoolean, + IsArray, + IsISO8601, + IsOptional, +} from 'class-validator'; +import { SettingsDto } from './settings.dto'; +import { TimetableDto } from './timetable.dto'; + +export class UserDTO { + //@IsString() + //status: string; + + @IsString() + firstname: string; + + @IsString() + lastname: string; + + @IsEmail() + email: string; + + @IsString() + profileURL: string; + + @IsISO8601() + createdAt: string; + + @IsISO8601() + lastLogin: string; + + @IsBoolean() + loggedIn: boolean; + + @IsArray() + friends: string[]; + + @IsOptional() + settings?: SettingsDto; + + @IsArray() + timetables: TimetableDto[]; +} diff --git a/server/src/user/user.controller.spec.ts b/server/src/user/user.controller.spec.ts new file mode 100644 index 000000000..7057a1a89 --- /dev/null +++ b/server/src/user/user.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { UserController } from './user.controller'; + +describe('UserController', () => { + let controller: UserController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [UserController], + }).compile(); + + controller = module.get(UserController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/server/src/user/user.controller.ts b/server/src/user/user.controller.ts new file mode 100644 index 000000000..92065e09d --- /dev/null +++ b/server/src/user/user.controller.ts @@ -0,0 +1,53 @@ +import { Controller, Get, Put, Param, Post, Body } from '@nestjs/common'; +import { UserService } from './user.service'; +import { EventDto, SettingsDto, TimetableDto } from './dto'; + +@Controller('user') +export class UserController { + constructor(private userService: UserService) {} + + @Get('profile/:userId') + getUserInfo(@Param('userId') userId: string) { + try { + return this.userService.getUserInfo(userId); + } catch (e) { + return e; + } + } + + @Get('settings/:userId') + getUserSettings(@Param('userId') userId: string) { + return this.userService.getUserSettings(userId); + } + + @Put('settings') + setUserSettings( + @Body('userId') userId: string, + @Body('setting') setting: SettingsDto, + ) { + this.userService.setUserSettings(userId, setting); + } + + @Get('timetable/:userId') + getUserTimetables(@Param('userId') userId: string) { + return null; + } + + @Post('timetable') + createUserTimetable( + @Body('timetableId') timetableId: string, + @Body('selectedCourses') selectedCourses: string[], + @Body('selectedClasses') selectedClasses: any[], // change type later + @Body('createdEvents') createdEvents: EventDto[], + ) { + console.log(timetableId, selectedCourses, selectedClasses, createdEvents); + } + + @Put('timetable') + editUserTimetable( + @Body('userId') userId: string, + @Body('timetable') timetable: TimetableDto, + ) { + console.log(userId, timetable); + } +} diff --git a/server/src/user/user.module.ts b/server/src/user/user.module.ts new file mode 100644 index 000000000..569d7329f --- /dev/null +++ b/server/src/user/user.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { UserService } from './user.service'; +import { UserController } from './user.controller'; + +@Module({ + providers: [UserService], + controllers: [UserController], +}) +export class UserModule {} diff --git a/server/src/user/user.service.spec.ts b/server/src/user/user.service.spec.ts new file mode 100644 index 000000000..873de8ac4 --- /dev/null +++ b/server/src/user/user.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { UserService } from './user.service'; + +describe('UserService', () => { + let service: UserService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [UserService], + }).compile(); + + service = module.get(UserService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts new file mode 100644 index 000000000..14a2618f7 --- /dev/null +++ b/server/src/user/user.service.ts @@ -0,0 +1,86 @@ +import { Injectable } from '@nestjs/common'; +import { SettingsDto, UserDTO, EventDto, TimetableDto } from './dto'; +import { PrismaService } from 'src/prisma/prisma.service'; + +const prisma = new PrismaService(); +@Injectable() +export class UserService { + async getUserInfo(_userId: string): Promise { + try { + const { userId, ...userData } = await prisma.user.findUniqueOrThrow({ + where: { userId: _userId }, + include: { + timetable: { + include: { + createdEvents: true, + }, + }, + }, + }); + + const data = { + ...userData, + createdAt: userData.createdAt.toISOString(), + // deleteUserAt: userData.deleteUserAt.toISOString(), + lastLogin: userData.lastLogin.toISOString(), + loggedIn: true, // Change this later + friends: [], // Need to add friends relation to the DB + timetables: userData.timetable.map((t) => { + return { + timetableId: t.id, + selectedCourses: t.selectedCourses, + events: t.createdEvents, + }; + }), + }; + + return Promise.resolve(data); + } catch (e) { + throw new Error(e); // Not sure why I'm just catching and rethrowing - probably should process the error in some way + } + } + + async getUserSettings(_userId: string): Promise { + try { + const settings = await prisma.settings.findUniqueOrThrow({ + where: { userId: _userId }, + }); + + return Promise.resolve(settings); + } catch (e) { + throw new Error(e); + } + } + + setUserSettings(userId: string, setting: SettingsDto): void {} + + async getUserTimetables(_userId: string): Promise { + try { + const res = await prisma.timetable.findMany({ + where: { userId: _userId }, + include: { + selectedClasses: true, + createdEvents: true, + }, + }); + + // Destructure timetables object to make it easier to work with + const timetables = res.map((t) => { + return { ...t, timetableId: t.id, events: t.createdEvents }; + }); + + return Promise.resolve(timetables); + } catch (e) { + throw new Error(e); + } + } + + createUserTimetable( + timetableId: string, + selectedCourses: string[], + selectedClasses: any[], + createdEvents: EventDto[], + ): void {} + + editUserTimetable(userId: string, timetable: TimetableDto): void {} +} From bc0b6811f270a8147da55a7636ca57b3189a9c3c Mon Sep 17 00:00:00 2001 From: ray Date: Sat, 11 May 2024 21:37:44 +1000 Subject: [PATCH 21/92] TLS error potentially caused by UNSW IT not renewing cert --- server/Dockerfile | 2 ++ server/nest-cli.json | 1 + server/package.json | 4 +++- server/pnpm-lock.yaml | 24 +++++++++++++----------- server/prisma/schema.prisma | 2 +- server/src/app.module.ts | 2 +- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index c0921ef7a..2c894315d 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -19,6 +19,8 @@ COPY package.json pnpm-lock.yaml ./ RUN pnpm install --production COPY --from=builder /server . +RUN npx prisma generate + EXPOSE 3001 diff --git a/server/nest-cli.json b/server/nest-cli.json index b4625a634..563742eca 100644 --- a/server/nest-cli.json +++ b/server/nest-cli.json @@ -5,6 +5,7 @@ "compilerOptions": { "deleteOutDir": true, "assets": [ + "../prisma/*", "./proto/*" ] } diff --git a/server/package.json b/server/package.json index 0d470cb60..c1e79c55b 100644 --- a/server/package.json +++ b/server/package.json @@ -29,8 +29,10 @@ "@nestjs/platform-express": "^10.0.0", "@prisma/client": "5.13.0", "@quixo3/prisma-session-store": "^3.1.13", + "@types/express-session": "^1.18.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", + "dotenv": "^16.4.5", "express-session": "^1.18.0", "google-protobuf": "^3.21.2", "grpc_tools_node_protoc_ts": "^5.3.3", @@ -42,7 +44,7 @@ "ts-protoc-gen": "^0.15.0" }, "devDependencies": { - "@nestjs/cli": "^10.0.0", + "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index 9e4192a12..a4c0cc5ba 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -32,12 +32,18 @@ dependencies: '@quixo3/prisma-session-store': specifier: ^3.1.13 version: 3.1.13(@prisma/client@5.13.0)(express-session@1.18.0) + '@types/express-session': + specifier: ^1.18.0 + version: 1.18.0 class-transformer: specifier: ^0.5.1 version: 0.5.1 class-validator: specifier: ^0.14.1 version: 0.14.1 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 express-session: specifier: ^1.18.0 version: 1.18.0 @@ -68,7 +74,7 @@ dependencies: devDependencies: '@nestjs/cli': - specifier: ^10.0.0 + specifier: ^10.3.2 version: 10.3.2 '@nestjs/schematics': specifier: ^10.0.0 @@ -1330,13 +1336,11 @@ packages: dependencies: '@types/connect': 3.4.38 '@types/node': 20.12.10 - dev: true /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: '@types/node': 20.12.10 - dev: true /@types/cookiejar@2.1.5: resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} @@ -1367,7 +1371,12 @@ packages: '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - dev: true + + /@types/express-session@1.18.0: + resolution: {integrity: sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==} + dependencies: + '@types/express': 4.17.21 + dev: false /@types/express@4.17.21: resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -1376,7 +1385,6 @@ packages: '@types/express-serve-static-core': 4.19.0 '@types/qs': 6.9.15 '@types/serve-static': 1.15.7 - dev: true /@types/graceful-fs@4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -1386,7 +1394,6 @@ packages: /@types/http-errors@2.0.4: resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: true /@types/istanbul-lib-coverage@2.0.6: resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -1421,7 +1428,6 @@ packages: /@types/mime@1.3.5: resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: true /@types/node@20.12.10: resolution: {integrity: sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw==} @@ -1430,11 +1436,9 @@ packages: /@types/qs@6.9.15: resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} - dev: true /@types/range-parser@1.2.7: resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: true /@types/semver@7.5.8: resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} @@ -1445,7 +1449,6 @@ packages: dependencies: '@types/mime': 1.3.5 '@types/node': 20.12.10 - dev: true /@types/serve-static@1.15.7: resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} @@ -1453,7 +1456,6 @@ packages: '@types/http-errors': 2.0.4 '@types/node': 20.12.10 '@types/send': 0.17.4 - dev: true /@types/stack-utils@2.0.3: resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index 89fc4d291..a3f35dabe 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -81,4 +81,4 @@ model Session { expiresAt DateTime } -// future: add settings for individual timetables, rounded corners, show only open classes etc? \ No newline at end of file +// future: add settings for individual timetables, rounded corners, show only open classes etc? diff --git a/server/src/app.module.ts b/server/src/app.module.ts index b7b64ee07..169e94f06 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -10,7 +10,7 @@ import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ ConfigModule.forRoot(), - AuthModule, + // AuthModule, AutoModule, UserModule, FriendModule, From d45b10918f792277d5f3dd4c5a9a8d24352a5380 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 12 May 2024 13:55:06 +1000 Subject: [PATCH 22/92] updating dockerignore to ignore extra bloat and gitignore to ignore migrations for prisma. --- .gitignore | 2 +- server/.dockerignore | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ec5781078..df908cdf0 100644 --- a/.gitignore +++ b/.gitignore @@ -72,4 +72,4 @@ typings/ # Mac stuff .DS_Store - +server/prisma/migrations/ diff --git a/server/.dockerignore b/server/.dockerignore index 93f136199..88764e401 100644 --- a/server/.dockerignore +++ b/server/.dockerignore @@ -1,2 +1,7 @@ node_modules npm-debug.log +test +.gitignore +.prettierrc +Dockerfile +README.md \ No newline at end of file From 18a4de6d311e8f0b09acf19939c29f345c2f9cb1 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 12 May 2024 13:55:30 +1000 Subject: [PATCH 23/92] Updated format for files --- server/src/auto/auto.controller.ts | 15 +- server/src/auto/auto.service.ts | 34 ++-- server/src/auto/dto/auto.dto.ts | 20 +- server/src/proto/autotimetabler_grpc_pb.d.ts | 101 +++++++--- server/src/proto/autotimetabler_pb.d.ts | 198 +++++++++++-------- 5 files changed, 236 insertions(+), 132 deletions(-) diff --git a/server/src/auto/auto.controller.ts b/server/src/auto/auto.controller.ts index cb652f31f..100976ec3 100644 --- a/server/src/auto/auto.controller.ts +++ b/server/src/auto/auto.controller.ts @@ -1,8 +1,15 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from '@nestjs/common'; import { AutoService } from './auto.service'; import { autoDTO } from './dto/auto.dto'; - @Controller('auto') export class AutoController { constructor(private readonly autoService: AutoService) {} @@ -11,8 +18,4 @@ export class AutoController { create(@Body() userRequestConstraints: autoDTO) { return this.autoService.getAutoTimetable(userRequestConstraints); } - } - - - diff --git a/server/src/auto/auto.service.ts b/server/src/auto/auto.service.ts index ca701703d..406facc2e 100644 --- a/server/src/auto/auto.service.ts +++ b/server/src/auto/auto.service.ts @@ -11,11 +11,13 @@ export class AutoService { async getAutoTimetable(@Body() autoService: autoDTO) { return getAuto(autoService); } -} - +} export const getAuto = async (data: autoDTO) => { - let client = new AutoTimetablerClient(config.auto, grpc.credentials.createInsecure()); + const client = new AutoTimetablerClient( + config.auto, + grpc.credentials.createInsecure(), + ); const constraints = new TimetableConstraints(); constraints.setStart(data.start); @@ -23,23 +25,29 @@ export const getAuto = async (data: autoDTO) => { constraints.setDays(data.days); constraints.setGap(data.gap); constraints.setMaxdays(data.maxdays); - - data.periodInfoList.forEach(thisPeriod => { + + data.periodInfoList.forEach((thisPeriod) => { const thisPeriodInfo = new TimetableConstraints.PeriodInfo(); - thisPeriodInfo.setPeriodsperclass(thisPeriod.periodsPerClass) - thisPeriodInfo.setPeriodtimesList(thisPeriod.periodTimes) - thisPeriodInfo.setDurationsList(thisPeriod.durations) - - constraints.addPeriodinfo(thisPeriodInfo) - }) + thisPeriodInfo.setPeriodsperclass(thisPeriod.periodsPerClass); + thisPeriodInfo.setPeriodtimesList(thisPeriod.periodTimes); + thisPeriodInfo.setDurationsList(thisPeriod.durations); + + constraints.addPeriodinfo(thisPeriodInfo); + }); client.findBestTimetable(constraints, (err, response) => { if (err) { console.error('error was found: ' + err); - throw new HttpException('An error occurred when handling the request.', HttpStatus.BAD_GATEWAY); + throw new HttpException( + 'An error occurred when handling the request.', + HttpStatus.BAD_GATEWAY, + ); } else { - return JSON.stringify({ given: response.getTimesList(), optimal: response.getOptimal()}); + return JSON.stringify({ + given: response.getTimesList(), + optimal: response.getOptimal(), + }); } }); }; diff --git a/server/src/auto/dto/auto.dto.ts b/server/src/auto/dto/auto.dto.ts index 34c73f4a8..12e529fb8 100644 --- a/server/src/auto/dto/auto.dto.ts +++ b/server/src/auto/dto/auto.dto.ts @@ -1,12 +1,12 @@ export class autoDTO { - start: number; - end: number; - days: string; - gap: number; - maxdays: number; - periodInfoList: { - periodsPerClass: number; - periodTimes: Array; - durations: Array; - }[] + start: number; + end: number; + days: string; + gap: number; + maxdays: number; + periodInfoList: { + periodsPerClass: number; + periodTimes: Array; + durations: Array; + }[]; } diff --git a/server/src/proto/autotimetabler_grpc_pb.d.ts b/server/src/proto/autotimetabler_grpc_pb.d.ts index 122458dae..02fc10520 100644 --- a/server/src/proto/autotimetabler_grpc_pb.d.ts +++ b/server/src/proto/autotimetabler_grpc_pb.d.ts @@ -1,41 +1,98 @@ -// package: +// package: // file: autotimetabler.proto /* tslint:disable */ /* eslint-disable */ -import * as grpc from "@grpc/grpc-js"; -import * as autotimetabler_pb from "./autotimetabler_pb"; +import * as grpc from '@grpc/grpc-js'; +import * as autotimetabler_pb from './autotimetabler_pb'; -interface IAutoTimetablerService extends grpc.ServiceDefinition { - findBestTimetable: IAutoTimetablerService_IFindBestTimetable; +interface IAutoTimetablerService + extends grpc.ServiceDefinition { + findBestTimetable: IAutoTimetablerService_IFindBestTimetable; } -interface IAutoTimetablerService_IFindBestTimetable extends grpc.MethodDefinition { - path: "/AutoTimetabler/FindBestTimetable"; - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; +interface IAutoTimetablerService_IFindBestTimetable + extends grpc.MethodDefinition< + autotimetabler_pb.TimetableConstraints, + autotimetabler_pb.AutoTimetableResponse + > { + path: '/AutoTimetabler/FindBestTimetable'; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; } export const AutoTimetablerService: IAutoTimetablerService; export interface IAutoTimetablerServer { - findBestTimetable: grpc.handleUnaryCall; + findBestTimetable: grpc.handleUnaryCall< + autotimetabler_pb.TimetableConstraints, + autotimetabler_pb.AutoTimetableResponse + >; } export interface IAutoTimetablerClient { - findBestTimetable(request: autotimetabler_pb.TimetableConstraints, callback: (error: grpc.ServiceError | null, response: autotimetabler_pb.AutoTimetableResponse) => void): grpc.ClientUnaryCall; - findBestTimetable(request: autotimetabler_pb.TimetableConstraints, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: autotimetabler_pb.AutoTimetableResponse) => void): grpc.ClientUnaryCall; - findBestTimetable(request: autotimetabler_pb.TimetableConstraints, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: autotimetabler_pb.AutoTimetableResponse) => void): grpc.ClientUnaryCall; + findBestTimetable( + request: autotimetabler_pb.TimetableConstraints, + callback: ( + error: grpc.ServiceError | null, + response: autotimetabler_pb.AutoTimetableResponse, + ) => void, + ): grpc.ClientUnaryCall; + findBestTimetable( + request: autotimetabler_pb.TimetableConstraints, + metadata: grpc.Metadata, + callback: ( + error: grpc.ServiceError | null, + response: autotimetabler_pb.AutoTimetableResponse, + ) => void, + ): grpc.ClientUnaryCall; + findBestTimetable( + request: autotimetabler_pb.TimetableConstraints, + metadata: grpc.Metadata, + options: Partial, + callback: ( + error: grpc.ServiceError | null, + response: autotimetabler_pb.AutoTimetableResponse, + ) => void, + ): grpc.ClientUnaryCall; } -export class AutoTimetablerClient extends grpc.Client implements IAutoTimetablerClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); - public findBestTimetable(request: autotimetabler_pb.TimetableConstraints, callback: (error: grpc.ServiceError | null, response: autotimetabler_pb.AutoTimetableResponse) => void): grpc.ClientUnaryCall; - public findBestTimetable(request: autotimetabler_pb.TimetableConstraints, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: autotimetabler_pb.AutoTimetableResponse) => void): grpc.ClientUnaryCall; - public findBestTimetable(request: autotimetabler_pb.TimetableConstraints, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: autotimetabler_pb.AutoTimetableResponse) => void): grpc.ClientUnaryCall; +export class AutoTimetablerClient + extends grpc.Client + implements IAutoTimetablerClient +{ + constructor( + address: string, + credentials: grpc.ChannelCredentials, + options?: object, + ); + public findBestTimetable( + request: autotimetabler_pb.TimetableConstraints, + callback: ( + error: grpc.ServiceError | null, + response: autotimetabler_pb.AutoTimetableResponse, + ) => void, + ): grpc.ClientUnaryCall; + public findBestTimetable( + request: autotimetabler_pb.TimetableConstraints, + metadata: grpc.Metadata, + callback: ( + error: grpc.ServiceError | null, + response: autotimetabler_pb.AutoTimetableResponse, + ) => void, + ): grpc.ClientUnaryCall; + public findBestTimetable( + request: autotimetabler_pb.TimetableConstraints, + metadata: grpc.Metadata, + options: Partial, + callback: ( + error: grpc.ServiceError | null, + response: autotimetabler_pb.AutoTimetableResponse, + ) => void, + ): grpc.ClientUnaryCall; } diff --git a/server/src/proto/autotimetabler_pb.d.ts b/server/src/proto/autotimetabler_pb.d.ts index 0a7c95033..7e775b720 100644 --- a/server/src/proto/autotimetabler_pb.d.ts +++ b/server/src/proto/autotimetabler_pb.d.ts @@ -1,101 +1,137 @@ -// package: +// package: // file: autotimetabler.proto /* tslint:disable */ /* eslint-disable */ -import * as jspb from "google-protobuf"; +import * as jspb from 'google-protobuf'; -export class TimetableConstraints extends jspb.Message { - getStart(): number; - setStart(value: number): TimetableConstraints; - getEnd(): number; - setEnd(value: number): TimetableConstraints; - getDays(): string; - setDays(value: string): TimetableConstraints; - getGap(): number; - setGap(value: number): TimetableConstraints; - getMaxdays(): number; - setMaxdays(value: number): TimetableConstraints; - clearPeriodinfoList(): void; - getPeriodinfoList(): Array; - setPeriodinfoList(value: Array): TimetableConstraints; - addPeriodinfo(value?: TimetableConstraints.PeriodInfo, index?: number): TimetableConstraints.PeriodInfo; +export class TimetableConstraints extends jspb.Message { + getStart(): number; + setStart(value: number): TimetableConstraints; + getEnd(): number; + setEnd(value: number): TimetableConstraints; + getDays(): string; + setDays(value: string): TimetableConstraints; + getGap(): number; + setGap(value: number): TimetableConstraints; + getMaxdays(): number; + setMaxdays(value: number): TimetableConstraints; + clearPeriodinfoList(): void; + getPeriodinfoList(): Array; + setPeriodinfoList( + value: Array, + ): TimetableConstraints; + addPeriodinfo( + value?: TimetableConstraints.PeriodInfo, + index?: number, + ): TimetableConstraints.PeriodInfo; - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): TimetableConstraints.AsObject; - static toObject(includeInstance: boolean, msg: TimetableConstraints): TimetableConstraints.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: TimetableConstraints, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): TimetableConstraints; - static deserializeBinaryFromReader(message: TimetableConstraints, reader: jspb.BinaryReader): TimetableConstraints; + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): TimetableConstraints.AsObject; + static toObject( + includeInstance: boolean, + msg: TimetableConstraints, + ): TimetableConstraints.AsObject; + static extensions: { [key: number]: jspb.ExtensionFieldInfo }; + static extensionsBinary: { + [key: number]: jspb.ExtensionFieldBinaryInfo; + }; + static serializeBinaryToWriter( + message: TimetableConstraints, + writer: jspb.BinaryWriter, + ): void; + static deserializeBinary(bytes: Uint8Array): TimetableConstraints; + static deserializeBinaryFromReader( + message: TimetableConstraints, + reader: jspb.BinaryReader, + ): TimetableConstraints; } export namespace TimetableConstraints { - export type AsObject = { - start: number, - end: number, - days: string, - gap: number, - maxdays: number, - periodinfoList: Array, - } - - - export class PeriodInfo extends jspb.Message { - getPeriodsperclass(): number; - setPeriodsperclass(value: number): PeriodInfo; - clearPeriodtimesList(): void; - getPeriodtimesList(): Array; - setPeriodtimesList(value: Array): PeriodInfo; - addPeriodtimes(value: number, index?: number): number; - clearDurationsList(): void; - getDurationsList(): Array; - setDurationsList(value: Array): PeriodInfo; - addDurations(value: number, index?: number): number; + export type AsObject = { + start: number; + end: number; + days: string; + gap: number; + maxdays: number; + periodinfoList: Array; + }; - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): PeriodInfo.AsObject; - static toObject(includeInstance: boolean, msg: PeriodInfo): PeriodInfo.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: PeriodInfo, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): PeriodInfo; - static deserializeBinaryFromReader(message: PeriodInfo, reader: jspb.BinaryReader): PeriodInfo; - } + export class PeriodInfo extends jspb.Message { + getPeriodsperclass(): number; + setPeriodsperclass(value: number): PeriodInfo; + clearPeriodtimesList(): void; + getPeriodtimesList(): Array; + setPeriodtimesList(value: Array): PeriodInfo; + addPeriodtimes(value: number, index?: number): number; + clearDurationsList(): void; + getDurationsList(): Array; + setDurationsList(value: Array): PeriodInfo; + addDurations(value: number, index?: number): number; - export namespace PeriodInfo { - export type AsObject = { - periodsperclass: number, - periodtimesList: Array, - durationsList: Array, - } - } + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): PeriodInfo.AsObject; + static toObject( + includeInstance: boolean, + msg: PeriodInfo, + ): PeriodInfo.AsObject; + static extensions: { [key: number]: jspb.ExtensionFieldInfo }; + static extensionsBinary: { + [key: number]: jspb.ExtensionFieldBinaryInfo; + }; + static serializeBinaryToWriter( + message: PeriodInfo, + writer: jspb.BinaryWriter, + ): void; + static deserializeBinary(bytes: Uint8Array): PeriodInfo; + static deserializeBinaryFromReader( + message: PeriodInfo, + reader: jspb.BinaryReader, + ): PeriodInfo; + } + export namespace PeriodInfo { + export type AsObject = { + periodsperclass: number; + periodtimesList: Array; + durationsList: Array; + }; + } } -export class AutoTimetableResponse extends jspb.Message { - clearTimesList(): void; - getTimesList(): Array; - setTimesList(value: Array): AutoTimetableResponse; - addTimes(value: number, index?: number): number; - getOptimal(): boolean; - setOptimal(value: boolean): AutoTimetableResponse; +export class AutoTimetableResponse extends jspb.Message { + clearTimesList(): void; + getTimesList(): Array; + setTimesList(value: Array): AutoTimetableResponse; + addTimes(value: number, index?: number): number; + getOptimal(): boolean; + setOptimal(value: boolean): AutoTimetableResponse; - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): AutoTimetableResponse.AsObject; - static toObject(includeInstance: boolean, msg: AutoTimetableResponse): AutoTimetableResponse.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: AutoTimetableResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): AutoTimetableResponse; - static deserializeBinaryFromReader(message: AutoTimetableResponse, reader: jspb.BinaryReader): AutoTimetableResponse; + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): AutoTimetableResponse.AsObject; + static toObject( + includeInstance: boolean, + msg: AutoTimetableResponse, + ): AutoTimetableResponse.AsObject; + static extensions: { [key: number]: jspb.ExtensionFieldInfo }; + static extensionsBinary: { + [key: number]: jspb.ExtensionFieldBinaryInfo; + }; + static serializeBinaryToWriter( + message: AutoTimetableResponse, + writer: jspb.BinaryWriter, + ): void; + static deserializeBinary(bytes: Uint8Array): AutoTimetableResponse; + static deserializeBinaryFromReader( + message: AutoTimetableResponse, + reader: jspb.BinaryReader, + ): AutoTimetableResponse; } export namespace AutoTimetableResponse { - export type AsObject = { - timesList: Array, - optimal: boolean, - } + export type AsObject = { + timesList: Array; + optimal: boolean; + }; } From 7e18c5c0c1a87cfc105775c29a9cfac93c6d37cd Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 12 May 2024 14:37:26 +1000 Subject: [PATCH 24/92] Prisma migration removed for now --- server/docker-compose.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/server/docker-compose.yaml b/server/docker-compose.yaml index ebf74fe85..1ac64e399 100644 --- a/server/docker-compose.yaml +++ b/server/docker-compose.yaml @@ -4,16 +4,16 @@ services: container_name: notangles-server image: notangles-server restart: always - build: . + build: + context: . + dockerfile: Dockerfile depends_on: - - database.notangles-db + - database.notangles_db ports: - '3001:3001' - links: - - database.notangles-db - database.notangles-db: - container_name: notangles-database + database.notangles_db: + container_name: notangles_database restart: always image: postgres:alpine ports: @@ -24,6 +24,7 @@ services: - POSTGRES_DB=${POSTGRES_DB} volumes: - postgres:/var/lib/postgresql/data + volumes: postgres: - name: server \ No newline at end of file + name: server From 18f3808de8a23d698fc632c13098ff58bd0d3436 Mon Sep 17 00:00:00 2001 From: ray Date: Mon, 13 May 2024 09:28:34 +1000 Subject: [PATCH 25/92] added example env files --- .gitignore | 3 +- server/.dockerignore | 4 +- server/.env.example | 12 ++ server/Dockerfile | 4 +- server/package.json | 1 + .../20240512002724_init/migration.sql | 112 ++++++++++++++++++ .../20240512232427_groups/migration.sql | 48 ++++++++ server/prisma/migrations/migration_lock.toml | 3 + server/prisma/schema.prisma | 21 ++-- 9 files changed, 197 insertions(+), 11 deletions(-) create mode 100644 server/.env.example create mode 100644 server/prisma/migrations/20240512002724_init/migration.sql create mode 100644 server/prisma/migrations/20240512232427_groups/migration.sql create mode 100644 server/prisma/migrations/migration_lock.toml diff --git a/.gitignore b/.gitignore index df908cdf0..646124621 100644 --- a/.gitignore +++ b/.gitignore @@ -66,10 +66,11 @@ typings/ # dotenv environment variables file .env +.env.dev +.env.prod # next.js build output .next # Mac stuff .DS_Store -server/prisma/migrations/ diff --git a/server/.dockerignore b/server/.dockerignore index 88764e401..76762c498 100644 --- a/server/.dockerignore +++ b/server/.dockerignore @@ -3,5 +3,7 @@ npm-debug.log test .gitignore .prettierrc +.git Dockerfile -README.md \ No newline at end of file +README.md +dist \ No newline at end of file diff --git a/server/.env.example b/server/.env.example new file mode 100644 index 000000000..bb271ef1f --- /dev/null +++ b/server/.env.example @@ -0,0 +1,12 @@ +POSTGRES_USER="postgres" +POSTGRES_DB="postgresdb" +POSTGRES_PASSWORD="verysneakypassword2022" +POSTGRES_PORT="5432" +DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${POSTGRES_PORT}/${POSTGRES_DB}?schema=public" +OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER="https://id.notangles.com.au" +OAUTH2_CLIENT_REGISTRATION_LOGIN_CLIENT_ID="abcd1234" +OAUTH2_CLIENT_REGISTRATION_LOGIN_CLIENT_SECRET="abcd1234" +OAUTH2_CLIENT_REGISTRATION_LOGIN_SCOPE="openid" +OAUTH2_CLIENT_REGISTRATION_LOGIN_REDIRECT_URI="http://somehost:3001/api/auth/callback/your_org" +OAUTH2_CLIENT_REGISTRATION_LOGIN_POST_LOGOUT_REDIRECT_URI="http://somehost:3001/api/auth/callback/your_org" +SESSION_SECRET="abcd1234" \ No newline at end of file diff --git a/server/Dockerfile b/server/Dockerfile index 2c894315d..30f9b9a50 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -5,6 +5,8 @@ RUN pnpm install @nestjs/cli WORKDIR /server COPY package.json pnpm-lock.yaml ./ +COPY prisma ./prisma/ + RUN pnpm i --no-frozen-lockfile COPY . . @@ -24,4 +26,4 @@ RUN npx prisma generate EXPOSE 3001 -CMD ["pnpm", "run", "start:prod"] +CMD ["pnpm", "run", "start:migrate:prod"] diff --git a/server/package.json b/server/package.json index c1e79c55b..296eb15d8 100644 --- a/server/package.json +++ b/server/package.json @@ -12,6 +12,7 @@ "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", + "start:migrate:prod": "prisma migrate deploy && npm run start:prod", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", diff --git a/server/prisma/migrations/20240512002724_init/migration.sql b/server/prisma/migrations/20240512002724_init/migration.sql new file mode 100644 index 000000000..1a75e7b52 --- /dev/null +++ b/server/prisma/migrations/20240512002724_init/migration.sql @@ -0,0 +1,112 @@ +-- CreateTable +CREATE TABLE "User" ( + "userId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "lastLogin" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP, + "firstname" TEXT, + "lastname" TEXT, + "email" TEXT NOT NULL, + "profileURL" TEXT, + + CONSTRAINT "User_pkey" PRIMARY KEY ("userId") +); + +-- CreateTable +CREATE TABLE "Event" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "location" TEXT, + "description" TEXT, + "colour" TEXT NOT NULL DEFAULT '#1F7E8C', + "day" TEXT NOT NULL, + "start" TIMESTAMP(3) NOT NULL, + "end" TIMESTAMP(3) NOT NULL, + "timetableId" TEXT, + + CONSTRAINT "Event_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Class" ( + "id" TEXT NOT NULL, + "classType" TEXT NOT NULL, + "courseName" TEXT, + "timetableId" TEXT +); + +-- CreateTable +CREATE TABLE "Timetable" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "selectedCourses" TEXT[], + "userId" TEXT NOT NULL, + + CONSTRAINT "Timetable_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Settings" ( + "userId" TEXT NOT NULL, + "is12HourMode" BOOLEAN NOT NULL, + "isDarkMode" BOOLEAN NOT NULL, + "isSquareEdges" BOOLEAN NOT NULL, + "isHideFullClasses" BOOLEAN NOT NULL, + "isDefaultUnscheduled" BOOLEAN NOT NULL, + "isHideClassInfo" BOOLEAN NOT NULL, + "isSortAlphabetic" BOOLEAN NOT NULL, + "isShowOnlyOpenClasses" BOOLEAN NOT NULL, + "isHideExamClasses" BOOLEAN NOT NULL, + "isConvertToLocalTimezone" BOOLEAN NOT NULL +); + +-- CreateTable +CREATE TABLE "Session" ( + "id" TEXT NOT NULL, + "sid" TEXT NOT NULL, + "data" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Session_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_UserFriends" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "Class_id_key" ON "Class"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "Timetable_id_key" ON "Timetable"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "Settings_userId_key" ON "Settings"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Session_sid_key" ON "Session"("sid"); + +-- CreateIndex +CREATE UNIQUE INDEX "_UserFriends_AB_unique" ON "_UserFriends"("A", "B"); + +-- CreateIndex +CREATE INDEX "_UserFriends_B_index" ON "_UserFriends"("B"); + +-- AddForeignKey +ALTER TABLE "Event" ADD CONSTRAINT "Event_timetableId_fkey" FOREIGN KEY ("timetableId") REFERENCES "Timetable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Class" ADD CONSTRAINT "Class_timetableId_fkey" FOREIGN KEY ("timetableId") REFERENCES "Timetable"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Timetable" ADD CONSTRAINT "Timetable_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Settings" ADD CONSTRAINT "Settings_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("userId") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_UserFriends" ADD CONSTRAINT "_UserFriends_A_fkey" FOREIGN KEY ("A") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_UserFriends" ADD CONSTRAINT "_UserFriends_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/prisma/migrations/20240512232427_groups/migration.sql b/server/prisma/migrations/20240512232427_groups/migration.sql new file mode 100644 index 000000000..9ed5e2872 --- /dev/null +++ b/server/prisma/migrations/20240512232427_groups/migration.sql @@ -0,0 +1,48 @@ +-- AlterTable +ALTER TABLE "Event" ADD COLUMN "groupId" TEXT; + +-- CreateTable +CREATE TABLE "Group" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "isPublic" BOOLEAN NOT NULL, + + CONSTRAINT "Group_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_GroupTimetable" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_GroupMember" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "_GroupTimetable_AB_unique" ON "_GroupTimetable"("A", "B"); + +-- CreateIndex +CREATE INDEX "_GroupTimetable_B_index" ON "_GroupTimetable"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_GroupMember_AB_unique" ON "_GroupMember"("A", "B"); + +-- CreateIndex +CREATE INDEX "_GroupMember_B_index" ON "_GroupMember"("B"); + +-- AddForeignKey +ALTER TABLE "_GroupTimetable" ADD CONSTRAINT "_GroupTimetable_A_fkey" FOREIGN KEY ("A") REFERENCES "Group"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_GroupTimetable" ADD CONSTRAINT "_GroupTimetable_B_fkey" FOREIGN KEY ("B") REFERENCES "Timetable"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_GroupMember" ADD CONSTRAINT "_GroupMember_A_fkey" FOREIGN KEY ("A") REFERENCES "Group"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_GroupMember" ADD CONSTRAINT "_GroupMember_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/prisma/migrations/migration_lock.toml b/server/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..fbffa92c2 --- /dev/null +++ b/server/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index a3f35dabe..ede76d9bc 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -1,9 +1,5 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - generator client { provider = "prisma-client-js" - // output = "../node_modules/.prisma/client" } datasource db { @@ -23,6 +19,16 @@ model User { settings Settings? friends User[] @relation("UserFriends") friendRequests User[] @relation("UserFriends") + groups Group[] @relation("GroupMember") +} + +model Group { + id String @id + name String + description String? + isPublic Boolean + timetables Timetable[] @relation("GroupTimetable") + members User[] @relation("GroupMember") } model Event { @@ -38,11 +44,12 @@ model Event { end DateTime timetable Timetable? @relation(fields: [timetableId], references: [id]) timetableId String? + groupId String? // Added to link an event to a group } model Class { id String @unique - classType String // e.g. Lecture, Tutorial, Laboratory, etc. Not putting into enum because there are other whacky classTypes + classType String // e.g. Lecture, Tutorial, Laboratory, etc. courseName String? Timetable Timetable? @relation(fields: [timetableId], references: [id], onDelete: Cascade) timetableId String? @@ -56,9 +63,9 @@ model Timetable { createdEvents Event[] user User @relation(fields: [userId], references: [userId], onDelete: Cascade) userId String + groups Group[] @relation("GroupTimetable") } -// Weak entity model Settings { userId String @unique user User @relation(fields: [userId], references: [userId]) @@ -80,5 +87,3 @@ model Session { data String @db.Text // MediumText may be needed for MySql expiresAt DateTime } - -// future: add settings for individual timetables, rounded corners, show only open classes etc? From adebb6a7fa297a9a408a0b23bd21da77237a6a4e Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Mon, 13 May 2024 18:35:46 +1000 Subject: [PATCH 26/92] Add PUT user/profile endpoint, and complete PUT user settings endpoint --- server/Dockerfile | 1 - server/docker-compose.yaml | 3 +- server/package-lock.json | 2039 ++++++++++++++++++++++++++++ server/package.json | 3 +- server/pnpm-lock.yaml | 3 + server/src/user/user.controller.ts | 43 +- server/src/user/user.service.ts | 63 +- 7 files changed, 2144 insertions(+), 11 deletions(-) create mode 100644 server/package-lock.json diff --git a/server/Dockerfile b/server/Dockerfile index 2c894315d..1107c0dc3 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -21,7 +21,6 @@ RUN pnpm install --production COPY --from=builder /server . RUN npx prisma generate - EXPOSE 3001 CMD ["pnpm", "run", "start:prod"] diff --git a/server/docker-compose.yaml b/server/docker-compose.yaml index ebf74fe85..8dfb819ae 100644 --- a/server/docker-compose.yaml +++ b/server/docker-compose.yaml @@ -14,6 +14,7 @@ services: database.notangles-db: container_name: notangles-database + hostname: notangles_database restart: always image: postgres:alpine ports: @@ -26,4 +27,4 @@ services: - postgres:/var/lib/postgresql/data volumes: postgres: - name: server \ No newline at end of file + name: server diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 000000000..afa01cebe --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,2039 @@ +{ + "name": "notangles-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "notangles-server", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@grpc/grpc-js": "1.10.7", + "@sentry/node": "7.114.0", + "@sentry/tracing": "7.114.0", + "body-parser": "1.20.2", + "buffer-from": "1.1.2", + "express": "4.18.2", + "google-protobuf": "3.21.2", + "grpc_tools_node_protoc_ts": "5.3.3", + "grpc-tools": "1.12.4", + "minimist": "1.2.8", + "ts-protoc-gen": "0.15.0" + }, + "devDependencies": { + "@types/express": "4.17.21", + "@types/node": "20.12.11", + "prettier": "3.2.5", + "ts-node": "10.9.2", + "typescript": "4.9.5" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.7.tgz", + "integrity": "sha512-ZMBVjSeDAz3tFSehyO6Pd08xZT1HfIwq3opbeM4cDlBh52gmwp0wVIPcQur53NN0ac68HMZ/7SF2rGRD5KmVmg==", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@sentry-internal/tracing": { + "version": "7.114.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.114.0.tgz", + "integrity": "sha512-dOuvfJN7G+3YqLlUY4HIjyWHaRP8vbOgF+OsE5w2l7ZEn1rMAaUbPntAR8AF9GBA6j2zWNoSo8e7GjbJxVofSg==", + "dependencies": { + "@sentry/core": "7.114.0", + "@sentry/types": "7.114.0", + "@sentry/utils": "7.114.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/core": { + "version": "7.114.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.114.0.tgz", + "integrity": "sha512-YnanVlmulkjgZiVZ9BfY9k6I082n+C+LbZo52MTvx3FY6RE5iyiPMpaOh67oXEZRWcYQEGm+bKruRxLVP6RlbA==", + "dependencies": { + "@sentry/types": "7.114.0", + "@sentry/utils": "7.114.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/integrations": { + "version": "7.114.0", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.114.0.tgz", + "integrity": "sha512-BJIBWXGKeIH0ifd7goxOS29fBA8BkEgVVCahs6xIOXBjX1IRS6PmX0zYx/GP23nQTfhJiubv2XPzoYOlZZmDxg==", + "dependencies": { + "@sentry/core": "7.114.0", + "@sentry/types": "7.114.0", + "@sentry/utils": "7.114.0", + "localforage": "^1.8.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/node": { + "version": "7.114.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.114.0.tgz", + "integrity": "sha512-cqvi+OHV1Hj64mIGHoZtLgwrh1BG6ntcRjDLlVNMqml5rdTRD3TvG21579FtlqHlwZpbpF7K5xkwl8e5KL2hGw==", + "dependencies": { + "@sentry-internal/tracing": "7.114.0", + "@sentry/core": "7.114.0", + "@sentry/integrations": "7.114.0", + "@sentry/types": "7.114.0", + "@sentry/utils": "7.114.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/tracing": { + "version": "7.114.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.114.0.tgz", + "integrity": "sha512-eldEYGADReZ4jWdN5u35yxLUSTOvjsiZAYd4KBEpf+Ii65n7g/kYOKAjNl7tHbrEG1EsMW4nDPWStUMk1w+tfg==", + "dependencies": { + "@sentry-internal/tracing": "7.114.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/types": { + "version": "7.114.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.114.0.tgz", + "integrity": "sha512-tsqkkyL3eJtptmPtT0m9W/bPLkU7ILY7nvwpi1hahA5jrM7ppoU0IMaQWAgTD+U3rzFH40IdXNBFb8Gnqcva4w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/utils": { + "version": "7.114.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.114.0.tgz", + "integrity": "sha512-319N90McVpupQ6vws4+tfCy/03AdtsU0MurIE4+W5cubHME08HtiEWlfacvAxX+yuKFhvdsO4K4BB/dj54ideg==", + "dependencies": { + "@sentry/types": "7.114.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz", + "integrity": "sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.12.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", + "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/grpc_tools_node_protoc_ts": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/grpc_tools_node_protoc_ts/-/grpc_tools_node_protoc_ts-5.3.3.tgz", + "integrity": "sha512-M/YrklvVXMtuuj9kb42PxeouZhs7Ul+R4e/31XwrankUcKL8cQQP50Q9q+KEHGyHQaPt6VtKKsxMgLaKbCxeww==", + "dependencies": { + "google-protobuf": "3.15.8", + "handlebars": "4.7.7" + }, + "bin": { + "protoc-gen-ts": "bin/protoc-gen-ts" + } + }, + "node_modules/grpc_tools_node_protoc_ts/node_modules/google-protobuf": { + "version": "3.15.8", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.15.8.tgz", + "integrity": "sha512-2jtfdqTaSxk0cuBJBtTTWsot4WtR9RVr2rXg7x7OoqiuOKopPrwXpM1G4dXIkLcUNRh3RKzz76C8IOkksZSeOw==" + }, + "node_modules/grpc-tools": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/grpc-tools/-/grpc-tools-1.12.4.tgz", + "integrity": "sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.5" + }, + "bin": { + "grpc_tools_node_protoc": "bin/protoc.js", + "grpc_tools_node_protoc_plugin": "bin/protoc_plugin.js" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "dependencies": { + "lie": "3.1.1" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/protobufjs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.0.tgz", + "integrity": "sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-protoc-gen": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/ts-protoc-gen/-/ts-protoc-gen-0.15.0.tgz", + "integrity": "sha512-TycnzEyrdVDlATJ3bWFTtra3SCiEP0W0vySXReAuEygXCUr1j2uaVyL0DhzjwuUdQoW5oXPwk6oZWeA0955V+g==", + "dependencies": { + "google-protobuf": "^3.15.5" + }, + "bin": { + "protoc-gen-ts": "bin/protoc-gen-ts" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + } + } +} diff --git a/server/package.json b/server/package.json index c1e79c55b..91ded51e0 100644 --- a/server/package.json +++ b/server/package.json @@ -41,7 +41,8 @@ "protobufjs": "4.1.3", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", - "ts-protoc-gen": "^0.15.0" + "ts-protoc-gen": "^0.15.0", + "uuid": "^9.0.1" }, "devDependencies": { "@nestjs/cli": "^10.3.2", diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index a4c0cc5ba..cd4f72d5e 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -71,6 +71,9 @@ dependencies: ts-protoc-gen: specifier: ^0.15.0 version: 0.15.0 + uuid: + specifier: ^9.0.1 + version: 9.0.1 devDependencies: '@nestjs/cli': diff --git a/server/src/user/user.controller.ts b/server/src/user/user.controller.ts index 92065e09d..1c1f3787c 100644 --- a/server/src/user/user.controller.ts +++ b/server/src/user/user.controller.ts @@ -1,6 +1,6 @@ import { Controller, Get, Put, Param, Post, Body } from '@nestjs/common'; import { UserService } from './user.service'; -import { EventDto, SettingsDto, TimetableDto } from './dto'; +import { EventDto, SettingsDto, TimetableDto, UserDTO } from './dto'; @Controller('user') export class UserController { @@ -15,17 +15,48 @@ export class UserController { } } + // Route is WIP, but had to prototype, otherwise database integrity checks will prevent anything from being added to DB + // Note that userDTO is not the body arg type as it has superfluous information (eg. timetable, settings - these are added in other routes) + @Put('profile') + setUserInfo( + @Body('userId') userId: string, + @Body('email') email: string, + @Body('firstName') firstName?: string, + @Body('lastName') lastName?: string, + ) { + try { + return this.userService.setUserProfile( + userId, + email, + firstName, + lastName, + ); + } catch (e) { + return e; + } + } + @Get('settings/:userId') getUserSettings(@Param('userId') userId: string) { return this.userService.getUserSettings(userId); } @Put('settings') + // @UsePipes(new ValidationPipe({ transform: true })) setUserSettings( @Body('userId') userId: string, - @Body('setting') setting: SettingsDto, + @Body('setting') setting: any, //SettingsDto, // This aint working - temp solution, should try transforming this class ) { - this.userService.setUserSettings(userId, setting); + try { + return this.userService.setUserSettings(userId, setting).then((res) => { + return { + status: 'Successfully edited user settings!', + data: res, + }; + }); + } catch (e) { + return e; + } } @Get('timetable/:userId') @@ -35,12 +66,14 @@ export class UserController { @Post('timetable') createUserTimetable( - @Body('timetableId') timetableId: string, + // Isn't this one randomly generated? + // @Body('timetableId') timetableId: string, + @Body('userId') userId: string, @Body('selectedCourses') selectedCourses: string[], @Body('selectedClasses') selectedClasses: any[], // change type later @Body('createdEvents') createdEvents: EventDto[], ) { - console.log(timetableId, selectedCourses, selectedClasses, createdEvents); + console.log(selectedCourses, selectedClasses, createdEvents); } @Put('timetable') diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index 14a2618f7..3cc711948 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import { SettingsDto, UserDTO, EventDto, TimetableDto } from './dto'; import { PrismaService } from 'src/prisma/prisma.service'; +import { v4 as uuidv4 } from 'uuid'; const prisma = new PrismaService(); @Injectable() @@ -40,6 +41,32 @@ export class UserService { } } + async setUserProfile( + _userId: string, + _email: string, + _firstName?: string, + _lastName?: string, + ): Promise { + try { + const test = { + userId: _userId, + firstname: _firstName, + lastname: _lastName, + email: _email, + }; + + return Promise.resolve( + prisma.user.upsert({ + where: { + userId: _userId, + }, + create: test, + update: test, + }), + ); + } catch (e) {} + } + async getUserSettings(_userId: string): Promise { try { const settings = await prisma.settings.findUniqueOrThrow({ @@ -52,7 +79,24 @@ export class UserService { } } - setUserSettings(userId: string, setting: SettingsDto): void {} + async setUserSettings( + _userId: string, + setting: SettingsDto, + ): Promise { + try { + return Promise.resolve( + prisma.settings.upsert({ + where: { + userId: _userId, + }, + create: { userId: _userId, ...setting }, + update: setting, + }), + ); + } catch (e) { + throw new Error(e); + } + } async getUserTimetables(_userId: string): Promise { try { @@ -76,11 +120,24 @@ export class UserService { } createUserTimetable( - timetableId: string, selectedCourses: string[], selectedClasses: any[], createdEvents: EventDto[], - ): void {} + ): void { + // try { + // // Generate random timetable id + // const timetableId = uuidv4(); + // const res = await prisma.timetable.create({ + // data: { + // id: timetableId, + // name: 'default', // Probably need this as a parameter + // selectedCourses: '', + // }, + // }); + // } catch (e) { + // throw new Error(e); + // } + } editUserTimetable(userId: string, timetable: TimetableDto): void {} } From b8e121512f198bfbbed884ec7ea5afb1f3336002 Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Mon, 13 May 2024 19:37:12 +1000 Subject: [PATCH 27/92] Complete POST timetable endpoint --- server/src/user/dto/timetable.dto.ts | 10 ++++ server/src/user/user.controller.ts | 24 ++++++++-- server/src/user/user.service.ts | 71 ++++++++++++++++++++-------- 3 files changed, 83 insertions(+), 22 deletions(-) diff --git a/server/src/user/dto/timetable.dto.ts b/server/src/user/dto/timetable.dto.ts index cde6c9966..37c85beb4 100644 --- a/server/src/user/dto/timetable.dto.ts +++ b/server/src/user/dto/timetable.dto.ts @@ -12,10 +12,20 @@ export class TimetableDto { events: EventDto[]; } +export class ClassDto { + // id: string; + classType: string; + courseName?: string; + // timetableId?: string; +} + export class EventDto { id: string; // Frontend generated event id name: string; location: string; description: string; colour: string; + day: string; + start: Date; + end: Date; } diff --git a/server/src/user/user.controller.ts b/server/src/user/user.controller.ts index 1c1f3787c..834af8a83 100644 --- a/server/src/user/user.controller.ts +++ b/server/src/user/user.controller.ts @@ -1,6 +1,6 @@ import { Controller, Get, Put, Param, Post, Body } from '@nestjs/common'; import { UserService } from './user.service'; -import { EventDto, SettingsDto, TimetableDto, UserDTO } from './dto'; +import { ClassDto, EventDto, SettingsDto, TimetableDto, UserDTO } from './dto'; @Controller('user') export class UserController { @@ -70,10 +70,28 @@ export class UserController { // @Body('timetableId') timetableId: string, @Body('userId') userId: string, @Body('selectedCourses') selectedCourses: string[], - @Body('selectedClasses') selectedClasses: any[], // change type later + @Body('selectedClasses') selectedClasses: ClassDto[], // change type later @Body('createdEvents') createdEvents: EventDto[], + @Body('timetableName') timetableName?: string, ) { - console.log(selectedCourses, selectedClasses, createdEvents); + try { + return this.userService + .createUserTimetable( + userId, + selectedCourses, + selectedClasses, + createdEvents, + timetableName, + ) + .then((res) => { + return { + status: 'Successfully found user and created their new timetable!', + data: res, + }; + }); + } catch (e) { + return e; + } } @Put('timetable') diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index 3cc711948..bfe293f25 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { SettingsDto, UserDTO, EventDto, TimetableDto } from './dto'; +import { SettingsDto, UserDTO, EventDto, TimetableDto, ClassDto } from './dto'; import { PrismaService } from 'src/prisma/prisma.service'; import { v4 as uuidv4 } from 'uuid'; @@ -119,24 +119,57 @@ export class UserService { } } - createUserTimetable( - selectedCourses: string[], - selectedClasses: any[], - createdEvents: EventDto[], - ): void { - // try { - // // Generate random timetable id - // const timetableId = uuidv4(); - // const res = await prisma.timetable.create({ - // data: { - // id: timetableId, - // name: 'default', // Probably need this as a parameter - // selectedCourses: '', - // }, - // }); - // } catch (e) { - // throw new Error(e); - // } + async createUserTimetable( + _userId: string, + _selectedCourses: string[], + _selectedClasses: ClassDto[], + _createdEvents: EventDto[], + _timetableName?: string, + ): Promise { + try { + // Generate random timetable id + const _timetableId = uuidv4(); + + // Create timetable + await prisma.timetable.create({ + data: { + id: _timetableId, + name: _timetableName, + selectedCourses: _selectedCourses, + userId: _userId, + }, + }); + + // Create classes + const classes = _selectedClasses.map((c) => { + const classId = uuidv4(); // Where is this being generated? For now generating on backend + return { + timetableId: _timetableId, + id: classId, + classType: c.classType, + courseName: c.courseName, + }; + }); + + await prisma.class.createMany({ + data: classes, + skipDuplicates: true, // Not sure when there would be duplicates, but whatevs + }); + + // Create events + const events = _createdEvents.map((ev) => { + return { ...ev, timetableId: _timetableId }; + }); + + await prisma.event.createMany({ + data: events, + skipDuplicates: true, + }); + + return Promise.resolve(_timetableId); + } catch (e) { + throw new Error(e); + } } editUserTimetable(userId: string, timetable: TimetableDto): void {} From 04f65d23ec535115ab193ee37fcd68abd187b0be Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Mon, 13 May 2024 23:03:45 +1000 Subject: [PATCH 28/92] Edit timetable endpoint completed (not tested though lol - will do later): --- server/src/user/dto/timetable.dto.ts | 7 ++- server/src/user/user.controller.ts | 13 +++- server/src/user/user.service.ts | 91 ++++++++++++++++++++++++++-- 3 files changed, 102 insertions(+), 9 deletions(-) diff --git a/server/src/user/dto/timetable.dto.ts b/server/src/user/dto/timetable.dto.ts index 37c85beb4..b107e8cf1 100644 --- a/server/src/user/dto/timetable.dto.ts +++ b/server/src/user/dto/timetable.dto.ts @@ -8,15 +8,16 @@ export class TimetableDto { @IsArray() @IsString({ each: true }) selectedCourses: string[]; - + selectedClasses: ClassDto[]; events: EventDto[]; + name?: string; } export class ClassDto { - // id: string; + id?: string; // TODO: double check (currently optional, if generated on the backend during creation of timetable) classType: string; courseName?: string; - // timetableId?: string; + timetableId?: string; } export class EventDto { diff --git a/server/src/user/user.controller.ts b/server/src/user/user.controller.ts index 834af8a83..37ee17f26 100644 --- a/server/src/user/user.controller.ts +++ b/server/src/user/user.controller.ts @@ -99,6 +99,17 @@ export class UserController { @Body('userId') userId: string, @Body('timetable') timetable: TimetableDto, ) { - console.log(userId, timetable); + try { + return this.editUserTimetable(userId, timetable).then((res) => { + return { + status: 'Successfully Edited timetable', + data: { + id: res, + }, + }; + }); + } catch (e) { + return e; + } } } diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index bfe293f25..9da9d6930 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -130,8 +130,8 @@ export class UserService { // Generate random timetable id const _timetableId = uuidv4(); - // Create timetable - await prisma.timetable.create({ + // Create timetable - needs to resolve before adding classes and events + const create_timetable = prisma.timetable.create({ data: { id: _timetableId, name: _timetableName, @@ -151,7 +151,7 @@ export class UserService { }; }); - await prisma.class.createMany({ + const create_classes = prisma.class.createMany({ data: classes, skipDuplicates: true, // Not sure when there would be duplicates, but whatevs }); @@ -161,16 +161,97 @@ export class UserService { return { ...ev, timetableId: _timetableId }; }); - await prisma.event.createMany({ + const create_events = prisma.event.createMany({ data: events, skipDuplicates: true, }); + await prisma.$transaction([ + create_timetable, + create_classes, + create_events, + ]); return Promise.resolve(_timetableId); } catch (e) { throw new Error(e); } } - editUserTimetable(userId: string, timetable: TimetableDto): void {} + async editUserTimetable( + _userId: string, + _timetable: TimetableDto, + ): Promise { + try { + // Modify timetable + const _timetableId = _timetable.timetableId; + const eventIds = _timetable.events.map((event) => event.id); + const classIds = _timetable.events.map((c) => c.id); + + const update_timetable = prisma.timetable.update({ + where: { + userId: _userId, + }, + data: { + name: _timetable.name, + selectedCourses: _timetable.selectedCourses, + }, + }); + + const delete_events = prisma.event.deleteMany({ + where: { + timetableId: _timetableId, + NOT: { + id: { in: eventIds }, + }, + }, + }); + + const delete_classes = prisma.class.deleteMany({ + where: { + timetableId: _timetableId, + NOT: { + id: { in: classIds }, + }, + }, + }); + + const update_events = _timetable.events.map((e) => + prisma.class.upsert({ + where: { id: e.id }, + update: e, + create: e, + }), + ); + + const update_classes = _timetable.selectedClasses.map((c) => + prisma.class.upsert({ + where: { id: c.id }, + update: { + // Can these even change? + classType: c.classType, + courseName: c.courseName, + }, + create: { + timetableId: c.timetableId, + id: c.id, + classType: c.classType, + courseName: c.courseName, + }, + }), + ); + + // TODO: YET TO BE TESTED + await prisma.$transaction([ + update_timetable, + delete_events, + update_events, + delete_classes, + update_classes, + ]); + + return Promise.resolve(_timetableId); + } catch (e) { + throw new Error(e); + } + } } From a5bf4d11509f58a7301fe2f32107501ff7f77dc1 Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Tue, 14 May 2024 18:05:11 +1000 Subject: [PATCH 29/92] GET profile endpoint fixed and completed --- server/src/user/user.controller.ts | 17 ++++++++++------- server/src/user/user.service.ts | 23 ++++++++++++++--------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/server/src/user/user.controller.ts b/server/src/user/user.controller.ts index 37ee17f26..3d9f86ce5 100644 --- a/server/src/user/user.controller.ts +++ b/server/src/user/user.controller.ts @@ -9,7 +9,12 @@ export class UserController { @Get('profile/:userId') getUserInfo(@Param('userId') userId: string) { try { - return this.userService.getUserInfo(userId); + return this.userService.getUserInfo(userId).then((data) => { + return { + status: 'Successsfully returned user profile', + data, + }; + }); } catch (e) { return e; } @@ -48,10 +53,10 @@ export class UserController { @Body('setting') setting: any, //SettingsDto, // This aint working - temp solution, should try transforming this class ) { try { - return this.userService.setUserSettings(userId, setting).then((res) => { + return this.userService.setUserSettings(userId, setting).then((data) => { return { status: 'Successfully edited user settings!', - data: res, + data, }; }); } catch (e) { @@ -100,12 +105,10 @@ export class UserController { @Body('timetable') timetable: TimetableDto, ) { try { - return this.editUserTimetable(userId, timetable).then((res) => { + return this.editUserTimetable(userId, timetable).then((id) => { return { status: 'Successfully Edited timetable', - data: { - id: res, - }, + data: { id }, }; }); } catch (e) { diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index 9da9d6930..e3a1ecd00 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -8,16 +8,18 @@ const prisma = new PrismaService(); export class UserService { async getUserInfo(_userId: string): Promise { try { - const { userId, ...userData } = await prisma.user.findUniqueOrThrow({ - where: { userId: _userId }, - include: { - timetable: { - include: { - createdEvents: true, + const { userId, timetable, ...userData } = + await prisma.user.findUniqueOrThrow({ + where: { userId: _userId }, + include: { + timetable: { + include: { + createdEvents: true, + selectedClasses: true, + }, }, }, - }, - }); + }); const data = { ...userData, @@ -26,9 +28,12 @@ export class UserService { lastLogin: userData.lastLogin.toISOString(), loggedIn: true, // Change this later friends: [], // Need to add friends relation to the DB - timetables: userData.timetable.map((t) => { + // Annnoying that the DTO and the schema have differently named fields so have to do this + timetables: timetable.map((t) => { return { + name: t.name, timetableId: t.id, + selectedClasses: t.selectedClasses, selectedCourses: t.selectedCourses, events: t.createdEvents, }; From 82b890b172824d3e3a4df111eeb0f7ed1061c315 Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Tue, 14 May 2024 18:16:02 +1000 Subject: [PATCH 30/92] Complete GET settings endpoint --- server/src/user/user.controller.ts | 7 ++++++- server/src/user/user.service.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/server/src/user/user.controller.ts b/server/src/user/user.controller.ts index 3d9f86ce5..ba46526b4 100644 --- a/server/src/user/user.controller.ts +++ b/server/src/user/user.controller.ts @@ -43,7 +43,12 @@ export class UserController { @Get('settings/:userId') getUserSettings(@Param('userId') userId: string) { - return this.userService.getUserSettings(userId); + return this.userService.getUserSettings(userId).then((data) => { + return { + status: 'Successfully found user and their settings!', + data, + }; + }); } @Put('settings') diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index e3a1ecd00..bd179e8ef 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -74,7 +74,7 @@ export class UserService { async getUserSettings(_userId: string): Promise { try { - const settings = await prisma.settings.findUniqueOrThrow({ + const { userId, ...settings } = await prisma.settings.findUniqueOrThrow({ where: { userId: _userId }, }); From 95c0fb82f8dda9dcc6e7a265bf40d8c491018edf Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Tue, 14 May 2024 18:47:06 +1000 Subject: [PATCH 31/92] GET timetable is working now --- server/src/user/user.controller.ts | 5 ++++- server/src/user/user.service.ts | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/server/src/user/user.controller.ts b/server/src/user/user.controller.ts index ba46526b4..1d33bb11a 100644 --- a/server/src/user/user.controller.ts +++ b/server/src/user/user.controller.ts @@ -71,9 +71,12 @@ export class UserController { @Get('timetable/:userId') getUserTimetables(@Param('userId') userId: string) { - return null; + return this.userService.getUserTimetables(userId).then((data) => { + return { status: `Successfully found user's timetable`, data }; + }); } + // Could look to change params to just TimetableDTO (this would involve making timetableId optional - is this desired?) @Post('timetable') createUserTimetable( // Isn't this one randomly generated? diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index bd179e8ef..fde25bed8 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -115,7 +115,13 @@ export class UserService { // Destructure timetables object to make it easier to work with const timetables = res.map((t) => { - return { ...t, timetableId: t.id, events: t.createdEvents }; + // Again, we should look into renaming events to createEvents to make this easier + const { id, createdEvents, ...otherTimetableProps } = t; + return { + ...otherTimetableProps, + timetableId: id, + events: createdEvents, + }; }); return Promise.resolve(timetables); From 68ace619efea064375d126c44650b843b1463dc5 Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Tue, 14 May 2024 19:50:18 +1000 Subject: [PATCH 32/92] Delete timetable endpoint completed --- server/prisma/schema.prisma | 2 +- server/src/user/user.controller.ts | 33 ++++++++++++++++++++++++++---- server/src/user/user.service.ts | 14 +++++++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index a3f35dabe..e886a7516 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -36,7 +36,7 @@ model Event { day String start DateTime end DateTime - timetable Timetable? @relation(fields: [timetableId], references: [id]) + timetable Timetable? @relation(fields: [timetableId], references: [id], onDelete: Cascade) // TODO: was there a reason this wasn't cascaded on delete? timetableId String? } diff --git a/server/src/user/user.controller.ts b/server/src/user/user.controller.ts index 1d33bb11a..207c8caf1 100644 --- a/server/src/user/user.controller.ts +++ b/server/src/user/user.controller.ts @@ -1,4 +1,12 @@ -import { Controller, Get, Put, Param, Post, Body } from '@nestjs/common'; +import { + Controller, + Get, + Put, + Param, + Post, + Body, + Delete, +} from '@nestjs/common'; import { UserService } from './user.service'; import { ClassDto, EventDto, SettingsDto, TimetableDto, UserDTO } from './dto'; @@ -113,10 +121,27 @@ export class UserController { @Body('timetable') timetable: TimetableDto, ) { try { - return this.editUserTimetable(userId, timetable).then((id) => { + return this.userService + .editUserTimetable(userId, timetable) + .then((id) => { + return { + status: 'Successfully edited timetable', + data: { id }, + }; + }); + } catch (e) { + return e; + } + } + + // Note - why do we need userId as a param? https://devsoc.atlassian.net/wiki/spaces/N/pages/1575168/Notangles+API + @Delete('timetable/:timetableId') + deleteUserTimetable(@Param('timetableId') timetableId: string) { + try { + return this.userService.deleteUserTimetable(timetableId).then((id) => { return { - status: 'Successfully Edited timetable', - data: { id }, + status: 'Successfully deleted timetable', + data: { timetableId: id }, }; }); } catch (e) { diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index fde25bed8..32c129ba7 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -265,4 +265,18 @@ export class UserService { throw new Error(e); } } + + async deleteUserTimetable(_timetableId: string): Promise { + try { + await prisma.timetable.delete({ + where: { + id: _timetableId, + }, + }); + + return Promise.resolve(_timetableId); + } catch (e) { + throw new Error(_timetableId); + } + } } From 28ede1b721c5de4018bf5475320d55f02a4b4212 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 19 May 2024 13:03:17 +1000 Subject: [PATCH 33/92] added better mapping for sql name convention --- server/prisma/schema.prisma | 55 ++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index ede76d9bc..1c1663182 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -13,30 +13,35 @@ model User { lastLogin DateTime? @default(now()) firstname String? lastname String? - email String + email String profileURL String? timetable Timetable[] settings Settings? - friends User[] @relation("UserFriends") - friendRequests User[] @relation("UserFriends") - groups Group[] @relation("GroupMember") + friends User[] @relation("user_friends") + friendRequests User[] @relation("user_friends") + groups Group[] @relation("group_members") + adminGroups Group[] @relation("admins") + @@map("users") + @@index([userId]) } model Group { - id String @id - name String - description String? - isPublic Boolean - timetables Timetable[] @relation("GroupTimetable") - members User[] @relation("GroupMember") + id String @id @default(uuid()) + name String + description String? + visibility GroupVisibility @default(PRIVATE) + timetables Timetable[] @relation("group_timetables") + members User[] @relation("group_members") + groupAdmins User[] @relation("admins") + @@map("groups") } model Event { - id String @id + id String @id @default(uuid()) name String location String? description String? - colour String @default("#1F7E8C") + colour String @default("#1F7E8C") // Notangles Blue // Event Time day String @@ -44,15 +49,17 @@ model Event { end DateTime timetable Timetable? @relation(fields: [timetableId], references: [id]) timetableId String? - groupId String? // Added to link an event to a group + groupIds String[] // Added to link an event to a group + @@map("events") } model Class { id String @unique - classType String // e.g. Lecture, Tutorial, Laboratory, etc. + classType ClassType courseName String? Timetable Timetable? @relation(fields: [timetableId], references: [id], onDelete: Cascade) timetableId String? + @@map("classes") } model Timetable { @@ -61,9 +68,10 @@ model Timetable { selectedCourses String[] selectedClasses Class[] createdEvents Event[] - user User @relation(fields: [userId], references: [userId], onDelete: Cascade) + user User[] userId String - groups Group[] @relation("GroupTimetable") + groups Group[] @relation("group_timetables") + @@map("timetables") } model Settings { @@ -79,6 +87,7 @@ model Settings { isShowOnlyOpenClasses Boolean isHideExamClasses Boolean isConvertToLocalTimezone Boolean + @@map("settings") } model Session { @@ -86,4 +95,18 @@ model Session { sid String @unique data String @db.Text // MediumText may be needed for MySql expiresAt DateTime + @@map("sessions") } + +enum GroupVisibility { + PUBLIC + PRIVATE + @@map("group_visibility") +} + +enum ClassType { + LECTURE + TUTORIAL + LAORATORY + OTHER +} \ No newline at end of file From 5ed1842f5f0b5d7f05352a4165cbbfa31aaee0c7 Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Mon, 20 May 2024 21:24:04 +1000 Subject: [PATCH 34/92] Add friend/unfriend endpoints --- server/src/friend/friend.controller.ts | 28 +++++++--- server/src/friend/friend.service.ts | 77 ++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 12 deletions(-) diff --git a/server/src/friend/friend.controller.ts b/server/src/friend/friend.controller.ts index 81b4cdf69..425d57c0e 100644 --- a/server/src/friend/friend.controller.ts +++ b/server/src/friend/friend.controller.ts @@ -11,18 +11,30 @@ export class FriendController { @Post() friendUsers(@Body() friendDto: friendDto) { - return this.friendService.friendUsers( - friendDto.senderId, - friendDto.sendeeId, - ); + return this.friendService + .friendUsers(friendDto.senderId, friendDto.sendeeId) + .then((id) => { + return { + status: 'Successfully added users as friends!', + data: { + id, + }, + }; + }); } @Delete() unfriendUsers(@Body() friendDTO: friendDto) { - return this.friendService.unfriendUsers( - friendDTO.senderId, - friendDTO.sendeeId, - ); + return this.friendService + .unfriendUsers(friendDTO.senderId, friendDTO.sendeeId) + .then((id) => { + return { + status: 'Successfully removed users as friends!', + data: { + id, + }, + }; + }); } @Post('request') diff --git a/server/src/friend/friend.service.ts b/server/src/friend/friend.service.ts index c3e3ed6c0..380951df1 100644 --- a/server/src/friend/friend.service.ts +++ b/server/src/friend/friend.service.ts @@ -1,17 +1,86 @@ import { Injectable } from '@nestjs/common'; +import { PrismaService } from 'src/prisma/prisma.service'; +const prisma = new PrismaService(); @Injectable({}) export class FriendService { findAllFriends(userId: string) { return { friends: 'none tbh.' }; } - friendUsers(senderId: string, sendeeId: string) { - return { senderId, sendeeId }; + async friendUsers(senderId: string, sendeeId: string): Promise { + try { + // How defensive should we be (checking if senderId exists, checking if sendee is already a friend)? + if (senderId === sendeeId) { + throw new Error('Cannot friend yourself'); + } + + await prisma.$transaction([ + prisma.user.update({ + where: { + userId: senderId, + }, + data: { + friends: { + connect: { + userId: sendeeId, + }, + }, + }, + }), + prisma.user.update({ + where: { + userId: sendeeId, + }, + data: { + friends: { + connect: { + userId: senderId, + }, + }, + }, + }), + ]); + + return Promise.resolve(sendeeId); + } catch (e) { + throw new Error(e); + } } - unfriendUsers(senderId: string, sendeeId: string) { - return { senderId, sendeeId }; + async unfriendUsers(senderId: string, sendeeId: string): Promise { + try { + await prisma.$transaction([ + prisma.user.update({ + where: { + userId: senderId, + }, + data: { + friends: { + disconnect: { + userId: sendeeId, + }, + }, + }, + }), + prisma.user.update({ + where: { + userId: sendeeId, + }, + data: { + friends: { + disconnect: { + userId: senderId, + }, + }, + }, + }), + ]); + + return Promise.resolve(sendeeId); + } catch (e) { + throw new Error(e); + } } sendFriendRequest(senderId: string, sendeeId: string) { From d8ac30e047a27d0b571881793890cc91e11509ca Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Mon, 20 May 2024 21:36:29 +1000 Subject: [PATCH 35/92] Add friends get req --- server/src/friend/friend.controller.ts | 7 ++++++- server/src/friend/friend.service.ts | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/server/src/friend/friend.controller.ts b/server/src/friend/friend.controller.ts index 425d57c0e..afcc1f08c 100644 --- a/server/src/friend/friend.controller.ts +++ b/server/src/friend/friend.controller.ts @@ -6,7 +6,12 @@ export class FriendController { constructor(private friendService: FriendService) {} @Get(':userId') findAllFriends(@Param('userId') userId: string) { - return this.friendService.findAllFriends(userId); + return this.friendService.findAllFriends(userId).then((data) => { + return { + status: "Found user's friends", + data, + }; + }); } @Post() diff --git a/server/src/friend/friend.service.ts b/server/src/friend/friend.service.ts index 380951df1..1805c916f 100644 --- a/server/src/friend/friend.service.ts +++ b/server/src/friend/friend.service.ts @@ -4,8 +4,19 @@ import { PrismaService } from 'src/prisma/prisma.service'; const prisma = new PrismaService(); @Injectable({}) export class FriendService { - findAllFriends(userId: string) { - return { friends: 'none tbh.' }; + async findAllFriends(userId: string) { + try { + const res = await prisma.user.findUniqueOrThrow({ + where: { userId }, + select: { + friends: true, + }, + }); + + return res.friends; + } catch (e) { + throw new Error(); + } } async friendUsers(senderId: string, sendeeId: string): Promise { From f3927534314b92a0e0f5b71c8ef0ed68af5f0fca Mon Sep 17 00:00:00 2001 From: Michael Siu Date: Wed, 22 May 2024 22:14:48 +1000 Subject: [PATCH 36/92] Friend request endpoints completed --- server/prisma/schema.prisma | 7 ++- server/src/friend/dto/friend.dto.ts | 10 ++-- server/src/friend/friend.controller.ts | 19 +++++-- server/src/friend/friend.service.ts | 76 ++++++++++++++++++++++++-- 4 files changed, 95 insertions(+), 17 deletions(-) diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index e886a7516..f5e0ba8a8 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -21,8 +21,11 @@ model User { profileURL String? timetable Timetable[] settings Settings? - friends User[] @relation("UserFriends") - friendRequests User[] @relation("UserFriends") + friends User[] @relation(name: "UserFriends") + friendOf User[] @relation(name: "UserFriends") + outgoing User[] @relation(name: "FriendRequests") + incoming User[] @relation(name: "FriendRequests") + } model Event { diff --git a/server/src/friend/dto/friend.dto.ts b/server/src/friend/dto/friend.dto.ts index ce9bb69b8..448776946 100644 --- a/server/src/friend/dto/friend.dto.ts +++ b/server/src/friend/dto/friend.dto.ts @@ -10,8 +10,8 @@ export class friendDto { sendeeId: string; } -export class friendRequestDto { - @IsString() - @IsNotEmpty() - requestId: string; -} +// export class friendRequestDto { +// @IsString() +// @IsNotEmpty() +// requestId: string; +// } diff --git a/server/src/friend/friend.controller.ts b/server/src/friend/friend.controller.ts index afcc1f08c..de53aff39 100644 --- a/server/src/friend/friend.controller.ts +++ b/server/src/friend/friend.controller.ts @@ -1,5 +1,5 @@ import { Body, Controller, Delete, Get, Param, Post } from '@nestjs/common'; -import { friendDto, friendRequestDto } from './dto'; +import { friendDto } from './dto'; import { FriendService } from './friend.service'; @Controller('friend') export class FriendController { @@ -15,9 +15,9 @@ export class FriendController { } @Post() - friendUsers(@Body() friendDto: friendDto) { + friendUsers(@Body() friendDTO: friendDto) { return this.friendService - .friendUsers(friendDto.senderId, friendDto.sendeeId) + .friendUsers(friendDTO.senderId, friendDTO.sendeeId) .then((id) => { return { status: 'Successfully added users as friends!', @@ -51,7 +51,16 @@ export class FriendController { } @Delete('request') - deleteFriendRequest(@Body() friendRequestDto: friendRequestDto) { - return this.friendService.deleteFriendRequest(friendRequestDto.requestId); + deleteFriendRequest(@Body() friendDTO: friendDto) { + return this.friendService + .deleteFriendRequest(friendDTO.senderId, friendDTO.sendeeId) + .then((id) => { + return { + status: 'Successfully rejected friend request!', + data: { + id, + }, + }; + }); } } diff --git a/server/src/friend/friend.service.ts b/server/src/friend/friend.service.ts index 1805c916f..cd034771f 100644 --- a/server/src/friend/friend.service.ts +++ b/server/src/friend/friend.service.ts @@ -15,7 +15,7 @@ export class FriendService { return res.friends; } catch (e) { - throw new Error(); + throw new Error(e); } } @@ -94,11 +94,77 @@ export class FriendService { } } - sendFriendRequest(senderId: string, sendeeId: string) { - return { senderId, sendeeId }; + // Note: This can also serve as accepting a friend req (lmk if we should decouple these functions) + async sendFriendRequest(senderId: string, sendeeId: string) { + // Again, how defensive should we be (could potentially add blocking friend reqs to already friended users) + try { + if (senderId === sendeeId) { + throw new Error('Cannot friend yourself'); + } + + // Check if there's corresponding incoming request first + const isIncoming = await prisma.user.findFirst({ + where: { + userId: senderId, + incoming: { + some: { + userId: sendeeId, + }, + }, + }, + }); + + let status; + // If so, we can just friend them + if (isIncoming) { + // Reversed order because the current sender has an incoming req, so they are the "sendee" of that transaction + await this.deleteFriendRequest(sendeeId, senderId); + await this.friendUsers(senderId, sendeeId); + status = 'Successfully accepted friend request'; + } else { + // Else, send outgoing friend request + await prisma.user.update({ + where: { + userId: senderId, + }, + data: { + outgoing: { + connect: { + userId: sendeeId, + }, + }, + }, + }); + status = 'Successfully sent friend request'; + } + + return Promise.resolve({ + status, + sendeeId, + }); + } catch (e) { + throw new Error(e); + } } - deleteFriendRequest(requestId: string) { - return { requestId }; + // sendee = receiver = incoming (f-req is coming into the sendee, so sendee is the id of user who made this api req) + async deleteFriendRequest(senderId: string, sendeeId: string) { + try { + await prisma.user.update({ + where: { + userId: sendeeId, + }, + data: { + incoming: { + disconnect: { + userId: senderId, + }, + }, + }, + }); + return Promise.resolve(senderId); + } catch (e) { + throw new Error(e); + } } } From 22951f6b32c56ead4bac89e5a6924716f8c324c1 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Fri, 24 May 2024 18:12:54 +1000 Subject: [PATCH 37/92] added a toggle for choosing private or public group --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 37 +++++++++++++++++-- .../addGroupDialog/AddGroupDialogActions.tsx | 2 +- .../addGroupDialog/AddGroupDialogContent.tsx | 21 +++++++++-- .../addGroupDialog/AddGroupDialogTitle.tsx | 2 +- .../sidebar/addGroupDialog/dummyData.tsx | 16 ++++---- 5 files changed, 61 insertions(+), 17 deletions(-) diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index 138895a9f..1ea651b08 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -4,11 +4,12 @@ import { Dialog, IconButton, Tooltip } from '@mui/material'; import AddGroupDialogActions from './AddGroupDialogActions'; import AddGroupDialogTitle from './AddGroupDialogTitle'; import AddGroupDialogContent from './AddGroupDialogContent'; - +import NetworkError from '../../../interfaces/NetworkError'; +import { API_URL } from '../../../api/config'; export interface FriendType { name: string; - zID: number; + zID: string; } const AddGroupDialog = () => { @@ -16,9 +17,35 @@ const AddGroupDialog = () => { const [groupName, setGroupName] = useState(''); const [selectedFriends, setSelectedFriends] = useState([]); const [groupImageURL, setGroupImageURL] = useState(''); + const [isPrivate, setIsPrivate] = useState(true); + + const handleCreateGroup = async () => { + try { + const res = await fetch(`${API_URL.timetable}`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + groupData: { + name: groupName, + visibility: 'PRIVATE', + timetableIDs: ['0', '1', '2'], + memberIDs: selectedFriends.map((friend) => friend.zID), + groupAdmins: ['0'], + groupImageURL: groupImageURL, + }, + groupID: 0, + }), + }); + + if (res.status !== 200) throw new NetworkError("Couldn't get response"); - const handleCreateGroup = () => { - // TODO call API + // return anything + } catch (error) { + throw new NetworkError("Couldn't get response"); + } }; const handleClose = () => { @@ -43,6 +70,8 @@ const AddGroupDialog = () => { setGroupImageURL={setGroupImageURL} setGroupName={setGroupName} setSelectedFriends={setSelectedFriends} + setIsPrivate={setIsPrivate} + isPrivate={isPrivate} />
    diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx index deb36dd72..8bfbf81c4 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx @@ -5,7 +5,7 @@ import { styled } from '@mui/system'; const StyledDialogActions = styled(DialogActions)` background-color: ${({ theme }) => theme.palette.background.paper}; - padding: 0px 60px 30px 0px; + padding: 0px 30px 30px 0px; `; interface AddGroupDialogActionsProps { diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx index 86fdd6ebb..037945f98 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx @@ -1,15 +1,14 @@ import React from 'react'; import { CheckCircle as CheckCircleIcon, RadioButtonUnchecked as RadioButtonUncheckedIcon } from '@mui/icons-material'; -import { Autocomplete, Checkbox, Chip, DialogContent, TextField, Tooltip } from '@mui/material'; +import { Autocomplete, Checkbox, Chip, DialogContent, Switch, TextField, Tooltip } from '@mui/material'; import { styled } from '@mui/system'; import EditImagePopOver from './EditImagePopOver'; import { friends } from './dummyData'; import { FriendType } from './AddGroupDialog'; - const StyledDialogContent = styled(DialogContent)` background-color: ${({ theme }) => theme.palette.background.paper}; - padding: 40px 60px; + padding: 30px 30px; gap: 20px; display: flex; flex-direction: column; @@ -38,11 +37,20 @@ const StyledUploadImageContainer = styled('div')` align-items: flex-end; `; +const StyledPrivacyContainer = styled('div')` + display: flex; + align-items: center; + width: 100%; + justify-content: space-between; +`; + interface AddGroupDialoContentProps { groupImageURL: string; setGroupImageURL: (url: string) => void; setGroupName: (groupName: string) => void; setSelectedFriends: (friends: FriendType[]) => void; + isPrivate: boolean; + setIsPrivate: (isPrivate: boolean) => void; } const AddGroupDialogContent: React.FC = ({ @@ -50,6 +58,8 @@ const AddGroupDialogContent: React.FC = ({ setGroupImageURL, setGroupName, setSelectedFriends, + isPrivate, + setIsPrivate, }) => { return ( @@ -95,6 +105,11 @@ const AddGroupDialogContent: React.FC = ({ }} renderInput={(params) => } /> + + +
    Private Group
    + setIsPrivate(e.target.checked)} /> +
    ); }; diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogTitle.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogTitle.tsx index 7e4d8c44b..1b038727e 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialogTitle.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogTitle.tsx @@ -5,7 +5,7 @@ import { styled } from '@mui/system'; const StyledDialogTitle = styled(DialogTitle)` background-color: ${({ theme }) => theme.palette.background.paper}; - padding: 40px; + padding: 30px; display: flex; flex-direction: row; justify-content: space-between; diff --git a/client/src/components/sidebar/addGroupDialog/dummyData.tsx b/client/src/components/sidebar/addGroupDialog/dummyData.tsx index f6bc8602c..f19236a8c 100644 --- a/client/src/components/sidebar/addGroupDialog/dummyData.tsx +++ b/client/src/components/sidebar/addGroupDialog/dummyData.tsx @@ -2,12 +2,12 @@ import { FriendType } from "./AddGroupDialog"; export const friends: FriendType[] = [ - { name: 'Shaam', zID: 532445 }, - { name: 'Ray', zID: 523495 }, - { name: 'hhlu', zID: 584290 }, - { name: 'Sohum', zID: 523840 }, - { name: 'Chanel', zID: 542567 }, - { name: 'Nikki', zID: 524596 }, - { name: 'Micky', zID: 523948 }, - { name: 'Jasmine', zID: 540938 }, + { name: 'Shaam', zID: '532445' }, + { name: 'Ray', zID: '523495' }, + { name: 'hhlu', zID: '584290' }, + { name: 'Sohum', zID: '523840' }, + { name: 'Chanel', zID: '542567' }, + { name: 'Nikki', zID: '524596' }, + { name: 'Micky', zID: '523948' }, + { name: 'Jasmine', zID: '540938' }, ]; From 8f8be4db6386410ac80235d2164ac693680db1c5 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Sat, 25 May 2024 10:20:45 +1000 Subject: [PATCH 38/92] fixed styling of group privacy to a select menu --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 13 ++++--- .../addGroupDialog/AddGroupDialogContent.tsx | 34 ++++++++++++------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index 1ea651b08..c5724a825 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -12,12 +12,17 @@ export interface FriendType { zID: string; } +export enum Privacy { + PRIVATE = 'private', + PUBLIC = 'public', +} + const AddGroupDialog = () => { const [isOpen, setIsOpen] = useState(false); const [groupName, setGroupName] = useState(''); const [selectedFriends, setSelectedFriends] = useState([]); const [groupImageURL, setGroupImageURL] = useState(''); - const [isPrivate, setIsPrivate] = useState(true); + const [privacy, setPrivacy] = useState(Privacy.PRIVATE); const handleCreateGroup = async () => { try { @@ -41,8 +46,6 @@ const AddGroupDialog = () => { }); if (res.status !== 200) throw new NetworkError("Couldn't get response"); - - // return anything } catch (error) { throw new NetworkError("Couldn't get response"); } @@ -70,8 +73,8 @@ const AddGroupDialog = () => { setGroupImageURL={setGroupImageURL} setGroupName={setGroupName} setSelectedFriends={setSelectedFriends} - setIsPrivate={setIsPrivate} - isPrivate={isPrivate} + setPrivacy={setPrivacy} + privacy={privacy} />
    diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx index 037945f98..4f9db9070 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { CheckCircle as CheckCircleIcon, RadioButtonUnchecked as RadioButtonUncheckedIcon } from '@mui/icons-material'; -import { Autocomplete, Checkbox, Chip, DialogContent, Switch, TextField, Tooltip } from '@mui/material'; +import { Autocomplete, Checkbox, Chip, DialogContent, FormControl, InputLabel, MenuItem, Select, Switch, TextField, Tooltip } from '@mui/material'; import { styled } from '@mui/system'; import EditImagePopOver from './EditImagePopOver'; import { friends } from './dummyData'; -import { FriendType } from './AddGroupDialog'; +import { FriendType, Privacy } from './AddGroupDialog'; const StyledDialogContent = styled(DialogContent)` background-color: ${({ theme }) => theme.palette.background.paper}; @@ -40,26 +40,26 @@ const StyledUploadImageContainer = styled('div')` const StyledPrivacyContainer = styled('div')` display: flex; align-items: center; - width: 100%; + width: 94%; justify-content: space-between; `; -interface AddGroupDialoContentProps { +interface AddGroupDialogContentProps { groupImageURL: string; setGroupImageURL: (url: string) => void; setGroupName: (groupName: string) => void; setSelectedFriends: (friends: FriendType[]) => void; - isPrivate: boolean; - setIsPrivate: (isPrivate: boolean) => void; + privacy: Privacy; + setPrivacy: (privacy: Privacy) => void; } -const AddGroupDialogContent: React.FC = ({ +const AddGroupDialogContent: React.FC = ({ groupImageURL, setGroupImageURL, setGroupName, setSelectedFriends, - isPrivate, - setIsPrivate, + privacy, + setPrivacy }) => { return ( @@ -106,10 +106,18 @@ const AddGroupDialogContent: React.FC = ({ renderInput={(params) => } /> - -
    Private Group
    - setIsPrivate(e.target.checked)} /> -
    + + Group Privacy + +
    ); }; From 48c1a935b14794b3ae2cfd5c958cff1815299950 Mon Sep 17 00:00:00 2001 From: ray Date: Sat, 25 May 2024 10:21:55 +1000 Subject: [PATCH 39/92] added groups endpoints --- server/prisma/schema.prisma | 1 + server/src/app.module.ts | 2 + server/src/group/dto/create-group.dto.ts | 1 + server/src/group/dto/update-group.dto.ts | 4 + server/src/group/entities/group.entity.ts | 1 + server/src/group/group.controller.spec.ts | 20 ++++ server/src/group/group.controller.ts | 106 ++++++++++++++++++++++ server/src/group/group.module.ts | 9 ++ server/src/group/group.service.spec.ts | 18 ++++ server/src/group/group.service.ts | 61 +++++++++++++ 10 files changed, 223 insertions(+) create mode 100644 server/src/group/dto/create-group.dto.ts create mode 100644 server/src/group/dto/update-group.dto.ts create mode 100644 server/src/group/entities/group.entity.ts create mode 100644 server/src/group/group.controller.spec.ts create mode 100644 server/src/group/group.controller.ts create mode 100644 server/src/group/group.module.ts create mode 100644 server/src/group/group.service.spec.ts create mode 100644 server/src/group/group.service.ts diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index 1c1663182..335620f36 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -29,6 +29,7 @@ model Group { id String @id @default(uuid()) name String description String? + imageURL String? visibility GroupVisibility @default(PRIVATE) timetables Timetable[] @relation("group_timetables") members User[] @relation("group_members") diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 169e94f06..a1943bdbb 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -7,6 +7,7 @@ import { AuthModule } from './auth/auth.module'; import { UserModule } from './user/user.module'; import { FriendModule } from './friend/friend.module'; import { ConfigModule } from '@nestjs/config'; +import { GroupModule } from './group/group.module'; @Module({ imports: [ ConfigModule.forRoot(), @@ -15,6 +16,7 @@ import { ConfigModule } from '@nestjs/config'; UserModule, FriendModule, PrismaModule, + GroupModule, ], controllers: [AppController], providers: [AppService], diff --git a/server/src/group/dto/create-group.dto.ts b/server/src/group/dto/create-group.dto.ts new file mode 100644 index 000000000..742fac549 --- /dev/null +++ b/server/src/group/dto/create-group.dto.ts @@ -0,0 +1 @@ +export class CreateGroupDto {} diff --git a/server/src/group/dto/update-group.dto.ts b/server/src/group/dto/update-group.dto.ts new file mode 100644 index 000000000..ddaa1b0f4 --- /dev/null +++ b/server/src/group/dto/update-group.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/mapped-types'; +import { CreateGroupDto } from './create-group.dto'; + +export class UpdateGroupDto extends PartialType(CreateGroupDto) {} diff --git a/server/src/group/entities/group.entity.ts b/server/src/group/entities/group.entity.ts new file mode 100644 index 000000000..f08776497 --- /dev/null +++ b/server/src/group/entities/group.entity.ts @@ -0,0 +1 @@ +export class Group {} diff --git a/server/src/group/group.controller.spec.ts b/server/src/group/group.controller.spec.ts new file mode 100644 index 000000000..9988380e7 --- /dev/null +++ b/server/src/group/group.controller.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { GroupController } from './group.controller'; +import { GroupService } from './group.service'; + +describe('GroupController', () => { + let controller: GroupController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [GroupController], + providers: [GroupService], + }).compile(); + + controller = module.get(GroupController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/server/src/group/group.controller.ts b/server/src/group/group.controller.ts new file mode 100644 index 000000000..609ece7c9 --- /dev/null +++ b/server/src/group/group.controller.ts @@ -0,0 +1,106 @@ +import { + Controller, + Get, + Post, + Put, + Delete, + Body, + Param, + NotFoundException, + ConflictException, + BadRequestException, +} from '@nestjs/common'; +import { GroupService } from './group.service'; +import { CreateGroupDto } from './dto/create-group.dto'; +import { UpdateGroupDto } from './dto/update-group.dto'; + +@Controller('group') +export class GroupController { + constructor(private readonly groupService: GroupService) {} + + @Get(':id') + async findOne(@Param('id') id: string) { + const group = await this.groupService.findOne(id); + if (!group) { + throw new NotFoundException({ + timestamp: new Date().toISOString(), + path: `/api/group/${id}`, + data: "Can't find group!", + }); + } + return { + status: 'Success message for fetching group.', + data: group, + }; + } + + @Post() + async create(@Body() createGroupDto: CreateGroupDto) { + try { + const group = await this.groupService.create(createGroupDto); + return { + status: 'Success message for creation of group.', + data: group, + }; + } catch (error) { + if (error.message === 'Group already exists') { + throw new ConflictException({ + status: 'Group with that ID already exists!', + data: createGroupDto, + }); + } + throw new BadRequestException({ + timestamp: new Date().toISOString(), + path: `/api/group`, + data: 'Message detailing what went wrong.', + }); + } + } + + @Put(':id') + async update(@Param('id') id: string, @Body() updateGroupDto: UpdateGroupDto) { + try { + const group = await this.groupService.update(id, updateGroupDto); + return { + status: 'Success message for updating of group.', + data: group, + }; + } catch (error) { + if (error.message === 'Group not found') { + throw new NotFoundException({ + timestamp: new Date().toISOString(), + path: `/api/group/${id}`, + data: "Can't find group!", + }); + } else if (error.message === 'Group already exists') { + throw new ConflictException({ + timestamp: new Date().toISOString(), + path: `/api/group/${id}`, + data: 'Message detailing what went wrong. ie already exists', + }); + } + throw new BadRequestException({ + timestamp: new Date().toISOString(), + path: `/api/group/${id}`, + data: 'Message detailing what went wrong.', + }); + } + } + + @Delete(':id') + async remove(@Param('id') id: string, @Body('userID') userID: string) { + try { + await this.groupService.remove(id); + return { + status: 'Success message for deletion of group.', + data: {}, + }; + } catch (error) { + throw new NotFoundException({ + timestamp: new Date().toISOString(), + path: `/api/group/${id}`, + data: error.message || 'Message detailing what went wrong.', + }); + } + } +} diff --git a/server/src/group/group.module.ts b/server/src/group/group.module.ts new file mode 100644 index 000000000..07d7e6396 --- /dev/null +++ b/server/src/group/group.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { GroupService } from './group.service'; +import { GroupController } from './group.controller'; + +@Module({ + controllers: [GroupController], + providers: [GroupService], +}) +export class GroupModule {} \ No newline at end of file diff --git a/server/src/group/group.service.spec.ts b/server/src/group/group.service.spec.ts new file mode 100644 index 000000000..495dd7969 --- /dev/null +++ b/server/src/group/group.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { GroupService } from './group.service'; + +describe('GroupService', () => { + let service: GroupService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [GroupService], + }).compile(); + + service = module.get(GroupService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/group/group.service.ts b/server/src/group/group.service.ts new file mode 100644 index 000000000..4cbf612fc --- /dev/null +++ b/server/src/group/group.service.ts @@ -0,0 +1,61 @@ +import { Injectable, NotFoundException, ConflictException } from '@nestjs/common'; +import { PrismaService } from '../prisma/prisma.service'; +import { CreateGroupDto } from './dto/create-group.dto'; +import { UpdateGroupDto } from './dto/update-group.dto'; + +@Injectable() +export class GroupService { + constructor(private readonly prisma: PrismaService) {} + + async create(createGroupDto: CreateGroupDto) { + try { + const group = await this.prisma.group.create({ + data: createGroupDto, + }); + return group; + } catch (error) { + if (error.code === 'P2002') { // Unique constraint failed + throw new ConflictException('Group already exists'); + } + throw error; + } + } + + async findOne(id: string) { + const group = await this.prisma.group.findUnique({ + where: { id }, + }); + if (!group) { + throw new NotFoundException('Group not found'); + } + return group; + } + + async update(id: string, updateGroupDto: UpdateGroupDto) { + try { + const group = await this.prisma.group.update({ + where: { id }, + data: updateGroupDto, + }); + return group; + } catch (error) { + if (error.code === 'P2025') { // Record not found + throw new NotFoundException('Group not found'); + } + throw error; + } + } + + async remove(id: string) { + try { + await this.prisma.group.delete({ + where: { id }, + }); + } catch (error) { + if (error.code === 'P2025') { // Record not found + throw new NotFoundException('Group not found'); + } + throw error; + } + } +} From ad72ad076ef5228691265ff9e1f46afa2ca04535 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 15:26:44 +1000 Subject: [PATCH 40/92] group post merged --- .../20240512002724_init/migration.sql | 112 ------------------ .../20240512232427_groups/migration.sql | 48 -------- .../migrations/20240526045449_/migration.sql | 86 ++++++++++++++ server/prisma/prisma-error-codes.enum.ts | 4 + server/prisma/schema.prisma | 12 +- server/src/group/dto/create-group.dto.ts | 16 +-- server/src/group/dto/index.ts | 0 server/src/group/dto/update-group.dto.ts | 14 +-- server/src/group/group.controller.ts | 15 +-- server/src/group/group.module.ts | 5 +- server/src/group/group.service.ts | 72 ++++++++--- server/src/user/user.module.ts | 3 +- server/src/user/user.service.ts | 65 +++++++--- 13 files changed, 227 insertions(+), 225 deletions(-) delete mode 100644 server/prisma/migrations/20240512002724_init/migration.sql delete mode 100644 server/prisma/migrations/20240512232427_groups/migration.sql create mode 100644 server/prisma/migrations/20240526045449_/migration.sql create mode 100644 server/prisma/prisma-error-codes.enum.ts create mode 100644 server/src/group/dto/index.ts diff --git a/server/prisma/migrations/20240512002724_init/migration.sql b/server/prisma/migrations/20240512002724_init/migration.sql deleted file mode 100644 index 1a75e7b52..000000000 --- a/server/prisma/migrations/20240512002724_init/migration.sql +++ /dev/null @@ -1,112 +0,0 @@ --- CreateTable -CREATE TABLE "User" ( - "userId" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "lastLogin" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP, - "firstname" TEXT, - "lastname" TEXT, - "email" TEXT NOT NULL, - "profileURL" TEXT, - - CONSTRAINT "User_pkey" PRIMARY KEY ("userId") -); - --- CreateTable -CREATE TABLE "Event" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "location" TEXT, - "description" TEXT, - "colour" TEXT NOT NULL DEFAULT '#1F7E8C', - "day" TEXT NOT NULL, - "start" TIMESTAMP(3) NOT NULL, - "end" TIMESTAMP(3) NOT NULL, - "timetableId" TEXT, - - CONSTRAINT "Event_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Class" ( - "id" TEXT NOT NULL, - "classType" TEXT NOT NULL, - "courseName" TEXT, - "timetableId" TEXT -); - --- CreateTable -CREATE TABLE "Timetable" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "selectedCourses" TEXT[], - "userId" TEXT NOT NULL, - - CONSTRAINT "Timetable_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Settings" ( - "userId" TEXT NOT NULL, - "is12HourMode" BOOLEAN NOT NULL, - "isDarkMode" BOOLEAN NOT NULL, - "isSquareEdges" BOOLEAN NOT NULL, - "isHideFullClasses" BOOLEAN NOT NULL, - "isDefaultUnscheduled" BOOLEAN NOT NULL, - "isHideClassInfo" BOOLEAN NOT NULL, - "isSortAlphabetic" BOOLEAN NOT NULL, - "isShowOnlyOpenClasses" BOOLEAN NOT NULL, - "isHideExamClasses" BOOLEAN NOT NULL, - "isConvertToLocalTimezone" BOOLEAN NOT NULL -); - --- CreateTable -CREATE TABLE "Session" ( - "id" TEXT NOT NULL, - "sid" TEXT NOT NULL, - "data" TEXT NOT NULL, - "expiresAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Session_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_UserFriends" ( - "A" TEXT NOT NULL, - "B" TEXT NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "Class_id_key" ON "Class"("id"); - --- CreateIndex -CREATE UNIQUE INDEX "Timetable_id_key" ON "Timetable"("id"); - --- CreateIndex -CREATE UNIQUE INDEX "Settings_userId_key" ON "Settings"("userId"); - --- CreateIndex -CREATE UNIQUE INDEX "Session_sid_key" ON "Session"("sid"); - --- CreateIndex -CREATE UNIQUE INDEX "_UserFriends_AB_unique" ON "_UserFriends"("A", "B"); - --- CreateIndex -CREATE INDEX "_UserFriends_B_index" ON "_UserFriends"("B"); - --- AddForeignKey -ALTER TABLE "Event" ADD CONSTRAINT "Event_timetableId_fkey" FOREIGN KEY ("timetableId") REFERENCES "Timetable"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Class" ADD CONSTRAINT "Class_timetableId_fkey" FOREIGN KEY ("timetableId") REFERENCES "Timetable"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Timetable" ADD CONSTRAINT "Timetable_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Settings" ADD CONSTRAINT "Settings_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("userId") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_UserFriends" ADD CONSTRAINT "_UserFriends_A_fkey" FOREIGN KEY ("A") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_UserFriends" ADD CONSTRAINT "_UserFriends_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/prisma/migrations/20240512232427_groups/migration.sql b/server/prisma/migrations/20240512232427_groups/migration.sql deleted file mode 100644 index 9ed5e2872..000000000 --- a/server/prisma/migrations/20240512232427_groups/migration.sql +++ /dev/null @@ -1,48 +0,0 @@ --- AlterTable -ALTER TABLE "Event" ADD COLUMN "groupId" TEXT; - --- CreateTable -CREATE TABLE "Group" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT, - "isPublic" BOOLEAN NOT NULL, - - CONSTRAINT "Group_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_GroupTimetable" ( - "A" TEXT NOT NULL, - "B" TEXT NOT NULL -); - --- CreateTable -CREATE TABLE "_GroupMember" ( - "A" TEXT NOT NULL, - "B" TEXT NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "_GroupTimetable_AB_unique" ON "_GroupTimetable"("A", "B"); - --- CreateIndex -CREATE INDEX "_GroupTimetable_B_index" ON "_GroupTimetable"("B"); - --- CreateIndex -CREATE UNIQUE INDEX "_GroupMember_AB_unique" ON "_GroupMember"("A", "B"); - --- CreateIndex -CREATE INDEX "_GroupMember_B_index" ON "_GroupMember"("B"); - --- AddForeignKey -ALTER TABLE "_GroupTimetable" ADD CONSTRAINT "_GroupTimetable_A_fkey" FOREIGN KEY ("A") REFERENCES "Group"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_GroupTimetable" ADD CONSTRAINT "_GroupTimetable_B_fkey" FOREIGN KEY ("B") REFERENCES "Timetable"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_GroupMember" ADD CONSTRAINT "_GroupMember_A_fkey" FOREIGN KEY ("A") REFERENCES "Group"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_GroupMember" ADD CONSTRAINT "_GroupMember_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/prisma/migrations/20240526045449_/migration.sql b/server/prisma/migrations/20240526045449_/migration.sql new file mode 100644 index 000000000..16374c60a --- /dev/null +++ b/server/prisma/migrations/20240526045449_/migration.sql @@ -0,0 +1,86 @@ +/* + Warnings: + + - You are about to drop the column `userId` on the `settings` table. All the data in the column will be lost. + - You are about to drop the column `userId` on the `timetables` table. All the data in the column will be lost. + - The primary key for the `users` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `userId` on the `users` table. All the data in the column will be lost. + - A unique constraint covering the columns `[userID]` on the table `settings` will be added. If there are existing duplicate values, this will fail. + - Added the required column `userID` to the `settings` table without a default value. This is not possible if the table is not empty. + - Added the required column `userID` to the `timetables` table without a default value. This is not possible if the table is not empty. + - Added the required column `userID` to the `users` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "_TimetableToUser" DROP CONSTRAINT "_TimetableToUser_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_admins" DROP CONSTRAINT "_admins_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_friend_requests" DROP CONSTRAINT "_friend_requests_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_friend_requests" DROP CONSTRAINT "_friend_requests_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_group_members" DROP CONSTRAINT "_group_members_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_user_friends" DROP CONSTRAINT "_user_friends_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_user_friends" DROP CONSTRAINT "_user_friends_B_fkey"; + +-- DropForeignKey +ALTER TABLE "settings" DROP CONSTRAINT "settings_userId_fkey"; + +-- DropIndex +DROP INDEX "settings_userId_key"; + +-- DropIndex +DROP INDEX "users_userId_idx"; + +-- AlterTable +ALTER TABLE "settings" DROP COLUMN "userId", +ADD COLUMN "userID" TEXT NOT NULL; + +-- AlterTable +ALTER TABLE "timetables" DROP COLUMN "userId", +ADD COLUMN "userID" TEXT NOT NULL; + +-- AlterTable +ALTER TABLE "users" DROP CONSTRAINT "users_pkey", +DROP COLUMN "userId", +ADD COLUMN "userID" TEXT NOT NULL, +ADD CONSTRAINT "users_pkey" PRIMARY KEY ("userID"); + +-- CreateIndex +CREATE UNIQUE INDEX "settings_userID_key" ON "settings"("userID"); + +-- CreateIndex +CREATE INDEX "users_userID_idx" ON "users"("userID"); + +-- AddForeignKey +ALTER TABLE "settings" ADD CONSTRAINT "settings_userID_fkey" FOREIGN KEY ("userID") REFERENCES "users"("userID") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_user_friends" ADD CONSTRAINT "_user_friends_A_fkey" FOREIGN KEY ("A") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_user_friends" ADD CONSTRAINT "_user_friends_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_friend_requests" ADD CONSTRAINT "_friend_requests_A_fkey" FOREIGN KEY ("A") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_friend_requests" ADD CONSTRAINT "_friend_requests_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_group_members" ADD CONSTRAINT "_group_members_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_admins" ADD CONSTRAINT "_admins_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_TimetableToUser" ADD CONSTRAINT "_TimetableToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/prisma/prisma-error-codes.enum.ts b/server/prisma/prisma-error-codes.enum.ts new file mode 100644 index 000000000..851fa1c93 --- /dev/null +++ b/server/prisma/prisma-error-codes.enum.ts @@ -0,0 +1,4 @@ +export enum PrismaErrorCode { + UNIQUE_CONSTRAINT_FAILED = 'P2002', + RECORD_NOT_FOUND = 'P2025', +} diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index 4554a81a4..ef68d5576 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -8,7 +8,7 @@ datasource db { } model User { - userId String @id // same as zid + userID String @id // same as zid createdAt DateTime @default(now()) lastLogin DateTime? @default(now()) firstname String? @@ -24,7 +24,7 @@ model User { adminGroups Group[] @relation(name: "admins") memberGroups Group[] @relation(name: "group_members") @@map("users") - @@index([userId]) + @@index([userID]) } @@ -68,20 +68,20 @@ model Class { } model Timetable { - id String @id @unique + id String @id @unique @default(uuid()) name String selectedCourses String[] selectedClasses Class[] createdEvents Event[] user User[] - userId String + userID String groups Group[] @relation("group_timetables") @@map("timetables") } model Settings { - userId String @unique - user User @relation(fields: [userId], references: [userId]) + userID String @unique + user User @relation(fields: [userID], references: [userID]) is12HourMode Boolean isDarkMode Boolean isSquareEdges Boolean diff --git a/server/src/group/dto/create-group.dto.ts b/server/src/group/dto/create-group.dto.ts index 7e2074671..4ba6c9fc2 100644 --- a/server/src/group/dto/create-group.dto.ts +++ b/server/src/group/dto/create-group.dto.ts @@ -1,9 +1,9 @@ export class CreateGroupDto { - readonly id: string; - readonly name: string; - readonly visibility?: string; - readonly timetableIDs: string[]; - readonly memberIDs: string[]; - readonly groupAdmins: string[]; - readonly groupImageURL?: string; - } \ No newline at end of file + name: string; + description?: string; + imageURL?: string; + visibility?: string; + timetableIDs: string[]; + memberIDs: string[]; + groupAdminIDs: string[]; +} diff --git a/server/src/group/dto/index.ts b/server/src/group/dto/index.ts new file mode 100644 index 000000000..e69de29bb diff --git a/server/src/group/dto/update-group.dto.ts b/server/src/group/dto/update-group.dto.ts index bb6e97bd7..f6bd09e52 100644 --- a/server/src/group/dto/update-group.dto.ts +++ b/server/src/group/dto/update-group.dto.ts @@ -1,8 +1,8 @@ export class UpdateGroupDto { - readonly name?: string; - readonly visibility?: string; - readonly timetableIDs?: string[]; - readonly memberIDs?: string[]; - readonly groupAdmins?: string[]; - readonly groupImageURL?: string; - } \ No newline at end of file + name?: string; + visibility?: string; + timetableIDs?: string[]; + memberIDs?: string[]; + groupAdmins?: string[]; + groupImageURL?: string; +} diff --git a/server/src/group/group.controller.ts b/server/src/group/group.controller.ts index 609ece7c9..d383dc51c 100644 --- a/server/src/group/group.controller.ts +++ b/server/src/group/group.controller.ts @@ -43,22 +43,19 @@ export class GroupController { data: group, }; } catch (error) { - if (error.message === 'Group already exists') { - throw new ConflictException({ - status: 'Group with that ID already exists!', - data: createGroupDto, - }); - } throw new BadRequestException({ timestamp: new Date().toISOString(), path: `/api/group`, - data: 'Message detailing what went wrong.', + data: `There was an error creating the group, the error: ${error}`, }); } } @Put(':id') - async update(@Param('id') id: string, @Body() updateGroupDto: UpdateGroupDto) { + async update( + @Param('id') id: string, + @Body() updateGroupDto: UpdateGroupDto, + ) { try { const group = await this.groupService.update(id, updateGroupDto); return { @@ -88,7 +85,7 @@ export class GroupController { } @Delete(':id') - async remove(@Param('id') id: string, @Body('userID') userID: string) { + async remove(@Param('id') id: string) { try { await this.groupService.remove(id); return { diff --git a/server/src/group/group.module.ts b/server/src/group/group.module.ts index 30da13028..498d1e7c9 100644 --- a/server/src/group/group.module.ts +++ b/server/src/group/group.module.ts @@ -2,9 +2,10 @@ import { Module } from '@nestjs/common'; import { GroupService } from './group.service'; import { GroupController } from './group.controller'; import { PrismaService } from 'src/prisma/prisma.service'; +import { UserService } from 'src/user/user.service'; @Module({ controllers: [GroupController], - providers: [GroupService, PrismaService], + providers: [GroupService, PrismaService, UserService], }) -export class GroupModule {} \ No newline at end of file +export class GroupModule {} diff --git a/server/src/group/group.service.ts b/server/src/group/group.service.ts index 4cbf612fc..22a13efb1 100644 --- a/server/src/group/group.service.ts +++ b/server/src/group/group.service.ts @@ -1,30 +1,74 @@ -import { Injectable, NotFoundException, ConflictException } from '@nestjs/common'; +import { + Injectable, + NotFoundException, + ConflictException, + HttpException, +} from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { CreateGroupDto } from './dto/create-group.dto'; import { UpdateGroupDto } from './dto/update-group.dto'; +import { UserService } from 'src/user/user.service'; +import { PrismaErrorCode } from 'prisma/prisma-error-codes.enum'; @Injectable() export class GroupService { - constructor(private readonly prisma: PrismaService) {} + constructor( + private readonly prisma: PrismaService, + private readonly user: UserService, + ) {} async create(createGroupDto: CreateGroupDto) { + const { + name, + timetableIDs, + memberIDs, + groupAdminIDs, + description = '', + imageURL = '', + } = createGroupDto; + + const data: any = { name, description, imageURL }; + try { - const group = await this.prisma.group.create({ - data: createGroupDto, - }); + const [timetables, members, admins] = await Promise.all([ + this.user.getTimetablesByIDs(timetableIDs), + this.user.getUsersByIDs(memberIDs), + this.user.getUsersByIDs(groupAdminIDs), + ]); + + if (timetables.length > 0) { + data.timetables = { + connect: timetables.map((timetable) => ({ id: timetable.id })), + }; + } + + if (members.length > 0) { + data.members = { + connect: members.map((member) => ({ id: member.userID })), + }; + } + + if (admins.length > 0) { + data.admins = { + connect: admins.map((admin) => ({ id: admin.userID })), + }; + } + + const group = await this.prisma.group.create({ data }); return group; } catch (error) { - if (error.code === 'P2002') { // Unique constraint failed + if (error.code === PrismaErrorCode.UNIQUE_CONSTRAINT_FAILED) { throw new ConflictException('Group already exists'); } - throw error; + throw new HttpException( + `There was an error: ${error.message}`, + error.status || 500, + ); } } async findOne(id: string) { - const group = await this.prisma.group.findUnique({ - where: { id }, - }); + const group = await this.prisma.group.findUnique({ where: { id } }); if (!group) { throw new NotFoundException('Group not found'); } @@ -39,7 +83,7 @@ export class GroupService { }); return group; } catch (error) { - if (error.code === 'P2025') { // Record not found + if (error.code === PrismaErrorCode.RECORD_NOT_FOUND) { throw new NotFoundException('Group not found'); } throw error; @@ -48,11 +92,9 @@ export class GroupService { async remove(id: string) { try { - await this.prisma.group.delete({ - where: { id }, - }); + await this.prisma.group.delete({ where: { id } }); } catch (error) { - if (error.code === 'P2025') { // Record not found + if (error.code === PrismaErrorCode.RECORD_NOT_FOUND) { throw new NotFoundException('Group not found'); } throw error; diff --git a/server/src/user/user.module.ts b/server/src/user/user.module.ts index 569d7329f..1b541b22a 100644 --- a/server/src/user/user.module.ts +++ b/server/src/user/user.module.ts @@ -1,9 +1,10 @@ import { Module } from '@nestjs/common'; import { UserService } from './user.service'; import { UserController } from './user.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; @Module({ - providers: [UserService], + providers: [UserService, PrismaService], controllers: [UserController], }) export class UserModule {} diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index 32c129ba7..15aca9ea5 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -2,14 +2,15 @@ import { Injectable } from '@nestjs/common'; import { SettingsDto, UserDTO, EventDto, TimetableDto, ClassDto } from './dto'; import { PrismaService } from 'src/prisma/prisma.service'; import { v4 as uuidv4 } from 'uuid'; +import { Timetable, User } from '@prisma/client'; -const prisma = new PrismaService(); @Injectable() export class UserService { + constructor(private readonly prisma: PrismaService) {} async getUserInfo(_userId: string): Promise { try { const { userId, timetable, ...userData } = - await prisma.user.findUniqueOrThrow({ + await this.prisma.user.findUniqueOrThrow({ where: { userId: _userId }, include: { timetable: { @@ -61,7 +62,7 @@ export class UserService { }; return Promise.resolve( - prisma.user.upsert({ + this.prisma.user.upsert({ where: { userId: _userId, }, @@ -74,7 +75,7 @@ export class UserService { async getUserSettings(_userId: string): Promise { try { - const { userId, ...settings } = await prisma.settings.findUniqueOrThrow({ + const { userId, ...settings } = await this.prisma.settings.findUniqueOrThrow({ where: { userId: _userId }, }); @@ -90,7 +91,7 @@ export class UserService { ): Promise { try { return Promise.resolve( - prisma.settings.upsert({ + this.prisma.settings.upsert({ where: { userId: _userId, }, @@ -105,7 +106,7 @@ export class UserService { async getUserTimetables(_userId: string): Promise { try { - const res = await prisma.timetable.findMany({ + const res = await this.prisma.timetable.findMany({ where: { userId: _userId }, include: { selectedClasses: true, @@ -142,7 +143,7 @@ export class UserService { const _timetableId = uuidv4(); // Create timetable - needs to resolve before adding classes and events - const create_timetable = prisma.timetable.create({ + const create_timetable = this.prisma.timetable.create({ data: { id: _timetableId, name: _timetableName, @@ -162,7 +163,7 @@ export class UserService { }; }); - const create_classes = prisma.class.createMany({ + const create_classes = this.prisma.class.createMany({ data: classes, skipDuplicates: true, // Not sure when there would be duplicates, but whatevs }); @@ -172,12 +173,12 @@ export class UserService { return { ...ev, timetableId: _timetableId }; }); - const create_events = prisma.event.createMany({ + const create_events = this.prisma.event.createMany({ data: events, skipDuplicates: true, }); - await prisma.$transaction([ + await this.prisma.$transaction([ create_timetable, create_classes, create_events, @@ -198,7 +199,7 @@ export class UserService { const eventIds = _timetable.events.map((event) => event.id); const classIds = _timetable.events.map((c) => c.id); - const update_timetable = prisma.timetable.update({ + const update_timetable = this.prisma.timetable.update({ where: { userId: _userId, }, @@ -208,7 +209,7 @@ export class UserService { }, }); - const delete_events = prisma.event.deleteMany({ + const delete_events = this.prisma.event.deleteMany({ where: { timetableId: _timetableId, NOT: { @@ -217,7 +218,7 @@ export class UserService { }, }); - const delete_classes = prisma.class.deleteMany({ + const delete_classes = this.prisma.class.deleteMany({ where: { timetableId: _timetableId, NOT: { @@ -227,7 +228,7 @@ export class UserService { }); const update_events = _timetable.events.map((e) => - prisma.class.upsert({ + this.prisma.class.upsert({ where: { id: e.id }, update: e, create: e, @@ -235,7 +236,7 @@ export class UserService { ); const update_classes = _timetable.selectedClasses.map((c) => - prisma.class.upsert({ + this.prisma.class.upsert({ where: { id: c.id }, update: { // Can these even change? @@ -252,7 +253,7 @@ export class UserService { ); // TODO: YET TO BE TESTED - await prisma.$transaction([ + await this.prisma.$transaction([ update_timetable, delete_events, update_events, @@ -266,9 +267,39 @@ export class UserService { } } + async getTimetablesByIDs(timetableIDs: string[]): Promise { + try { + const timetables = await this.prisma.timetable.findMany({ + where: { + id: { + in: timetableIDs, + }, + }, + }); + return timetables; + } catch (error) { + console.error('Error retrieving timetables:', error); + } + } + + async getUsersByIDs(userIDs: string[]): Promise { + try { + const users = await this.prisma.user.findMany({ + where: { + userID: { + in: userIDs, + }, + }, + }); + return users; + } catch (error) { + console.error('Error retrieving users:', error); + } + } + async deleteUserTimetable(_timetableId: string): Promise { try { - await prisma.timetable.delete({ + await this.prisma.timetable.delete({ where: { id: _timetableId, }, From 1d239c98203a6b541d2fc5f4ae52b31bd7eedcc4 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 16:04:53 +1000 Subject: [PATCH 41/92] added seed script --- server/package.json | 3 + server/prisma/seed.ts | 138 ++++++++++++++++++++++++++++++++ server/src/user/user.service.ts | 7 +- 3 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 server/prisma/seed.ts diff --git a/server/package.json b/server/package.json index 26235cfd8..bbf0dbd00 100644 --- a/server/package.json +++ b/server/package.json @@ -85,5 +85,8 @@ ], "coverageDirectory": "../coverage", "testEnvironment": "node" + }, + "prisma": { + "seed": "ts-node --transpile-only prisma/seed.ts" } } diff --git a/server/prisma/seed.ts b/server/prisma/seed.ts new file mode 100644 index 000000000..310ebbc26 --- /dev/null +++ b/server/prisma/seed.ts @@ -0,0 +1,138 @@ +import { PrismaClient } from '@prisma/client'; +const prisma = new PrismaClient(); + +async function main() { + const users = [ + { name: 'Shaam', zID: '532445' }, + { name: 'Ray', zID: '523495' }, + { name: 'hhlu', zID: '584290' }, + { name: 'Sohum', zID: '523840' }, + { name: 'Chanel', zID: '542567' }, + { name: 'Nikki', zID: '524596' }, + { name: 'Micky', zID: '523948' }, + { name: 'Jasmine', zID: '540938' }, + ]; + + for (const user of users) { + await prisma.user.create({ + data: { + userID: user.zID, + firstname: user.name, + email: `${user.name.toLowerCase()}@example.com`, + profileURL: `http://notangles.com/${user.name.toLowerCase()}`, + }, + }); + } + + const user1 = await prisma.user.findUnique({ + where: { userID: '532445' }, + }); + + const user2 = await prisma.user.findUnique({ + where: { userID: '523495' }, + }); + + const timetable1 = await prisma.timetable.create({ + data: { + name: 'Timetable 1', + selectedCourses: ['COMP4128', 'COMP6991'], + }, + }); + + const timetable2 = await prisma.timetable.create({ + data: { + name: 'Timetable 2', + selectedCourses: ['COMP3821', 'COMP9417'], + }, + }); + + const group1 = await prisma.group.create({ + data: { + name: 'Group 1', + description: 'This is group 1', + visibility: 'PRIVATE', + members: { + connect: [{ userID: user1.userID }, { userID: user2.userID }], + }, + groupAdmins: { + connect: [{ userID: user1.userID }], + }, + }, + }); + + const group2 = await prisma.group.create({ + data: { + name: 'Group 2', + description: 'This is group 2', + visibility: 'PUBLIC', + members: { + connect: [{ userID: user2.userID }], + }, + groupAdmins: { + connect: [{ userID: user2.userID }], + }, + }, + }); + + const event1 = await prisma.event.create({ + data: { + name: 'Event 1', + day: 'Monday', + start: new Date('2024-05-27T10:00:00Z'), + end: new Date('2024-05-27T12:00:00Z'), + groupIds: [group1.id, group2.id], + }, + }); + + const event2 = await prisma.event.create({ + data: { + name: 'Event 2', + day: 'Tuesday', + start: new Date('2024-05-28T14:00:00Z'), + end: new Date('2024-05-28T16:00:00Z'), + groupIds: [group1.id], + }, + }); + + await prisma.settings.create({ + data: { + userID: user1.userID, + is12HourMode: false, + isDarkMode: true, + isSquareEdges: false, + isHideFullClasses: true, + isDefaultUnscheduled: false, + isHideClassInfo: true, + isSortAlphabetic: true, + isShowOnlyOpenClasses: false, + isHideExamClasses: false, + isConvertToLocalTimezone: true, + }, + }); + + await prisma.settings.create({ + data: { + userID: user2.userID, + is12HourMode: true, + isDarkMode: false, + isSquareEdges: true, + isHideFullClasses: false, + isDefaultUnscheduled: true, + isHideClassInfo: false, + isSortAlphabetic: false, + isShowOnlyOpenClasses: true, + isHideExamClasses: true, + isConvertToLocalTimezone: false, + }, + }); +} + +main() + .then(async () => { + await prisma.$disconnect(); + }) + .catch(async (e) => { + console.error(e); + await prisma.$disconnect(); + process.exit(1); + }); diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index 15aca9ea5..b9f4b5ed6 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -75,9 +75,10 @@ export class UserService { async getUserSettings(_userId: string): Promise { try { - const { userId, ...settings } = await this.prisma.settings.findUniqueOrThrow({ - where: { userId: _userId }, - }); + const { userId, ...settings } = + await this.prisma.settings.findUniqueOrThrow({ + where: { userId: _userId }, + }); return Promise.resolve(settings); } catch (e) { From c22f262af2f2cfccae9c745cef672e2b440ae4d0 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 16:14:22 +1000 Subject: [PATCH 42/92] added seed script --- server/package.json | 3 --- server/prisma/seed.ts | 12 ++++++++---- server/src/user/user.service.ts | 7 +++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/server/package.json b/server/package.json index bbf0dbd00..26235cfd8 100644 --- a/server/package.json +++ b/server/package.json @@ -85,8 +85,5 @@ ], "coverageDirectory": "../coverage", "testEnvironment": "node" - }, - "prisma": { - "seed": "ts-node --transpile-only prisma/seed.ts" } } diff --git a/server/prisma/seed.ts b/server/prisma/seed.ts index 310ebbc26..444a4ab9e 100644 --- a/server/prisma/seed.ts +++ b/server/prisma/seed.ts @@ -14,8 +14,10 @@ async function main() { ]; for (const user of users) { - await prisma.user.create({ - data: { + await prisma.user.upsert({ + where: { userID: user.zID }, + update: {}, + create: { userID: user.zID, firstname: user.name, email: `${user.name.toLowerCase()}@example.com`, @@ -32,8 +34,10 @@ async function main() { where: { userID: '523495' }, }); - const timetable1 = await prisma.timetable.create({ - data: { + const timetable1 = await prisma.timetable.upsert({ + where: { id: 'Timetable 1' }, + update: {}, + create: { name: 'Timetable 1', selectedCourses: ['COMP4128', 'COMP6991'], }, diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index b9f4b5ed6..15aca9ea5 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -75,10 +75,9 @@ export class UserService { async getUserSettings(_userId: string): Promise { try { - const { userId, ...settings } = - await this.prisma.settings.findUniqueOrThrow({ - where: { userId: _userId }, - }); + const { userId, ...settings } = await this.prisma.settings.findUniqueOrThrow({ + where: { userId: _userId }, + }); return Promise.resolve(settings); } catch (e) { From 6cb13d74bc0657001b08cc659e2a5164ac254717 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 17:08:41 +1000 Subject: [PATCH 43/92] adding some minor changes with source copying --- server/Dockerfile | 2 +- server/prisma/prisma-error-codes.enum.ts | 4 ---- server/src/group/group.service.ts | 6 +++++- server/src/proto/autotimetabler_grpc_pb.d.ts | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 server/prisma/prisma-error-codes.enum.ts diff --git a/server/Dockerfile b/server/Dockerfile index a70f58e0b..49dcdefed 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -25,4 +25,4 @@ RUN npx prisma generate EXPOSE 3001 -CMD ["pnpm", "run", "start:migrate:prod"] +CMD ["pnpm", "run", "start:migrate:prod"] \ No newline at end of file diff --git a/server/prisma/prisma-error-codes.enum.ts b/server/prisma/prisma-error-codes.enum.ts deleted file mode 100644 index 851fa1c93..000000000 --- a/server/prisma/prisma-error-codes.enum.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum PrismaErrorCode { - UNIQUE_CONSTRAINT_FAILED = 'P2002', - RECORD_NOT_FOUND = 'P2025', -} diff --git a/server/src/group/group.service.ts b/server/src/group/group.service.ts index 22a13efb1..bbbdda216 100644 --- a/server/src/group/group.service.ts +++ b/server/src/group/group.service.ts @@ -8,7 +8,11 @@ import { PrismaService } from '../prisma/prisma.service'; import { CreateGroupDto } from './dto/create-group.dto'; import { UpdateGroupDto } from './dto/update-group.dto'; import { UserService } from 'src/user/user.service'; -import { PrismaErrorCode } from 'prisma/prisma-error-codes.enum'; + +export enum PrismaErrorCode { + UNIQUE_CONSTRAINT_FAILED = 'P2002', + RECORD_NOT_FOUND = 'P2025', +} @Injectable() export class GroupService { diff --git a/server/src/proto/autotimetabler_grpc_pb.d.ts b/server/src/proto/autotimetabler_grpc_pb.d.ts index 02fc10520..6c2cd086a 100644 --- a/server/src/proto/autotimetabler_grpc_pb.d.ts +++ b/server/src/proto/autotimetabler_grpc_pb.d.ts @@ -95,4 +95,4 @@ export class AutoTimetablerClient response: autotimetabler_pb.AutoTimetableResponse, ) => void, ): grpc.ClientUnaryCall; -} +} \ No newline at end of file From 0f3b5e72e09c3ba748060cf1e31359f889cfc0c7 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 17:23:17 +1000 Subject: [PATCH 44/92] seed file was causing crashes --- server/prisma/seed.ts | 142 ------------------------------------------ 1 file changed, 142 deletions(-) delete mode 100644 server/prisma/seed.ts diff --git a/server/prisma/seed.ts b/server/prisma/seed.ts deleted file mode 100644 index 444a4ab9e..000000000 --- a/server/prisma/seed.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -const prisma = new PrismaClient(); - -async function main() { - const users = [ - { name: 'Shaam', zID: '532445' }, - { name: 'Ray', zID: '523495' }, - { name: 'hhlu', zID: '584290' }, - { name: 'Sohum', zID: '523840' }, - { name: 'Chanel', zID: '542567' }, - { name: 'Nikki', zID: '524596' }, - { name: 'Micky', zID: '523948' }, - { name: 'Jasmine', zID: '540938' }, - ]; - - for (const user of users) { - await prisma.user.upsert({ - where: { userID: user.zID }, - update: {}, - create: { - userID: user.zID, - firstname: user.name, - email: `${user.name.toLowerCase()}@example.com`, - profileURL: `http://notangles.com/${user.name.toLowerCase()}`, - }, - }); - } - - const user1 = await prisma.user.findUnique({ - where: { userID: '532445' }, - }); - - const user2 = await prisma.user.findUnique({ - where: { userID: '523495' }, - }); - - const timetable1 = await prisma.timetable.upsert({ - where: { id: 'Timetable 1' }, - update: {}, - create: { - name: 'Timetable 1', - selectedCourses: ['COMP4128', 'COMP6991'], - }, - }); - - const timetable2 = await prisma.timetable.create({ - data: { - name: 'Timetable 2', - selectedCourses: ['COMP3821', 'COMP9417'], - }, - }); - - const group1 = await prisma.group.create({ - data: { - name: 'Group 1', - description: 'This is group 1', - visibility: 'PRIVATE', - members: { - connect: [{ userID: user1.userID }, { userID: user2.userID }], - }, - groupAdmins: { - connect: [{ userID: user1.userID }], - }, - }, - }); - - const group2 = await prisma.group.create({ - data: { - name: 'Group 2', - description: 'This is group 2', - visibility: 'PUBLIC', - members: { - connect: [{ userID: user2.userID }], - }, - groupAdmins: { - connect: [{ userID: user2.userID }], - }, - }, - }); - - const event1 = await prisma.event.create({ - data: { - name: 'Event 1', - day: 'Monday', - start: new Date('2024-05-27T10:00:00Z'), - end: new Date('2024-05-27T12:00:00Z'), - groupIds: [group1.id, group2.id], - }, - }); - - const event2 = await prisma.event.create({ - data: { - name: 'Event 2', - day: 'Tuesday', - start: new Date('2024-05-28T14:00:00Z'), - end: new Date('2024-05-28T16:00:00Z'), - groupIds: [group1.id], - }, - }); - - await prisma.settings.create({ - data: { - userID: user1.userID, - is12HourMode: false, - isDarkMode: true, - isSquareEdges: false, - isHideFullClasses: true, - isDefaultUnscheduled: false, - isHideClassInfo: true, - isSortAlphabetic: true, - isShowOnlyOpenClasses: false, - isHideExamClasses: false, - isConvertToLocalTimezone: true, - }, - }); - - await prisma.settings.create({ - data: { - userID: user2.userID, - is12HourMode: true, - isDarkMode: false, - isSquareEdges: true, - isHideFullClasses: false, - isDefaultUnscheduled: true, - isHideClassInfo: false, - isSortAlphabetic: false, - isShowOnlyOpenClasses: true, - isHideExamClasses: true, - isConvertToLocalTimezone: false, - }, - }); -} - -main() - .then(async () => { - await prisma.$disconnect(); - }) - .catch(async (e) => { - console.error(e); - await prisma.$disconnect(); - process.exit(1); - }); From 6d92dc0b5ff1a6cba41bb34867c659c988bba7ce Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 17:25:06 +1000 Subject: [PATCH 45/92] testing out types --- server/src/user/user.service.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index 15aca9ea5..5a154ba3d 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { SettingsDto, UserDTO, EventDto, TimetableDto, ClassDto } from './dto'; import { PrismaService } from 'src/prisma/prisma.service'; import { v4 as uuidv4 } from 'uuid'; -import { Timetable, User } from '@prisma/client'; +// import { Timetable, User } from '@prisma/client'; @Injectable() export class UserService { @@ -76,8 +76,8 @@ export class UserService { async getUserSettings(_userId: string): Promise { try { const { userId, ...settings } = await this.prisma.settings.findUniqueOrThrow({ - where: { userId: _userId }, - }); + where: { userId: _userId }, + }); return Promise.resolve(settings); } catch (e) { @@ -267,7 +267,7 @@ export class UserService { } } - async getTimetablesByIDs(timetableIDs: string[]): Promise { + async getTimetablesByIDs(timetableIDs: string[]): Promise { try { const timetables = await this.prisma.timetable.findMany({ where: { @@ -282,7 +282,7 @@ export class UserService { } } - async getUsersByIDs(userIDs: string[]): Promise { + async getUsersByIDs(userIDs: string[]): Promise { try { const users = await this.prisma.user.findMany({ where: { From 5d1cf20ad2fc4db8e523c547b386c3c9a77c1811 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 17:26:46 +1000 Subject: [PATCH 46/92] adding ci prisma gen --- .github/workflows/ci.yml | 3 +++ server/src/user/user.service.ts | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a46137791..f298d67bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,9 @@ jobs: - name: Install dependencies run: pnpm install --no-frozen-lockfile working-directory: ${{ matrix.component }} + - name: Generate Prisma Types from Schema + run: npx prisma generate + working-directory: ${{ matrix.component }} - name: Build run: pnpm run build working-directory: ${{ matrix.component }} diff --git a/server/src/user/user.service.ts b/server/src/user/user.service.ts index 5a154ba3d..15aca9ea5 100644 --- a/server/src/user/user.service.ts +++ b/server/src/user/user.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { SettingsDto, UserDTO, EventDto, TimetableDto, ClassDto } from './dto'; import { PrismaService } from 'src/prisma/prisma.service'; import { v4 as uuidv4 } from 'uuid'; -// import { Timetable, User } from '@prisma/client'; +import { Timetable, User } from '@prisma/client'; @Injectable() export class UserService { @@ -76,8 +76,8 @@ export class UserService { async getUserSettings(_userId: string): Promise { try { const { userId, ...settings } = await this.prisma.settings.findUniqueOrThrow({ - where: { userId: _userId }, - }); + where: { userId: _userId }, + }); return Promise.resolve(settings); } catch (e) { @@ -267,7 +267,7 @@ export class UserService { } } - async getTimetablesByIDs(timetableIDs: string[]): Promise { + async getTimetablesByIDs(timetableIDs: string[]): Promise { try { const timetables = await this.prisma.timetable.findMany({ where: { @@ -282,7 +282,7 @@ export class UserService { } } - async getUsersByIDs(userIDs: string[]): Promise { + async getUsersByIDs(userIDs: string[]): Promise { try { const users = await this.prisma.user.findMany({ where: { From cba92de3cf96b234694822c2f0b532b22716cff9 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 17:34:29 +1000 Subject: [PATCH 47/92] added server config --- client/src/api/config.ts | 9 +++++---- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 17 +++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/client/src/api/config.ts b/client/src/api/config.ts index da58fa147..2b05c7721 100644 --- a/client/src/api/config.ts +++ b/client/src/api/config.ts @@ -8,16 +8,17 @@ export enum Env { interface Config { timetable: string; auto: string; + server: string; } const LOCAL = 'http://localhost:3001'; const LIVE = 'https://timetable.csesoc.app'; const API_CONFIG: Record = Object.freeze({ - [Env.DEV]: { timetable: `${LOCAL}/api`, auto: `${LOCAL}/auto` }, - [Env.TEST]: { timetable: `${LOCAL}/api`, auto: `${LOCAL}/auto` }, - [Env.MOCK]: { timetable: `${LIVE}/api`, auto: `${LOCAL}/auto` }, - [Env.PROD]: { timetable: `${LIVE}/api`, auto: `${LIVE}/auto` }, + [Env.DEV]: { timetable: `${LOCAL}/api`, auto: `${LOCAL}/auto`, server: `${LOCAL}/api` }, + [Env.TEST]: { timetable: `${LOCAL}/api`, auto: `${LOCAL}/auto`, server: `${LOCAL}/api` }, + [Env.MOCK]: { timetable: `${LIVE}/api`, auto: `${LOCAL}/auto`, server: `${LOCAL}/api` }, + [Env.PROD]: { timetable: `${LIVE}/api`, auto: `${LIVE}/auto`, server: `${LIVE}/api` }, }); export const API_URL: Config = API_CONFIG[import.meta.env.VITE_APP_ENVIRONMENT || Env.DEV]; diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index c5724a825..089622d0f 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -26,22 +26,19 @@ const AddGroupDialog = () => { const handleCreateGroup = async () => { try { - const res = await fetch(`${API_URL.timetable}`, { + const res = await fetch(`${API_URL.server}/group`, { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ - groupData: { - name: groupName, - visibility: 'PRIVATE', - timetableIDs: ['0', '1', '2'], - memberIDs: selectedFriends.map((friend) => friend.zID), - groupAdmins: ['0'], - groupImageURL: groupImageURL, - }, - groupID: 0, + name: groupName, + visibility: 'PRIVATE', + timetableIDs: ['0', '1', '2'], + memberIDs: selectedFriends.map((friend) => friend.zID), + groupAdmins: ['0'], + groupImageURL: groupImageURL, }), }); From 8b710b2a824e2b68937f20d99633484f64e80b79 Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 26 May 2024 23:55:26 +1000 Subject: [PATCH 48/92] can call BE for groups --- server/.prettierrc 2 | 4 ++++ server/nest-cli 2.json | 12 ++++++++++++ server/src/app.controller 2.ts | 12 ++++++++++++ server/src/app.service 2.ts | 8 ++++++++ server/src/auth/authenticated.guard 2.ts | 9 +++++++++ server/src/auto/auto.module 2.ts | 9 +++++++++ server/src/friend/friend.module 2.ts | 9 +++++++++ server/src/group/group.controller.ts | 2 +- server/src/group/group.module 2.ts | 11 +++++++++++ server/src/group/group.service.ts | 9 ++++----- server/src/prisma/prisma.module 2.ts | 7 +++++++ server/src/prisma/prisma.service 2.ts | 17 +++++++++++++++++ server/src/user/user.module 2.ts | 10 ++++++++++ server/test/jest-e2e 2.json | 9 +++++++++ server/tsconfig.build 2.json | 4 ++++ 15 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 server/.prettierrc 2 create mode 100644 server/nest-cli 2.json create mode 100644 server/src/app.controller 2.ts create mode 100644 server/src/app.service 2.ts create mode 100644 server/src/auth/authenticated.guard 2.ts create mode 100644 server/src/auto/auto.module 2.ts create mode 100644 server/src/friend/friend.module 2.ts create mode 100644 server/src/group/group.module 2.ts create mode 100644 server/src/prisma/prisma.module 2.ts create mode 100644 server/src/prisma/prisma.service 2.ts create mode 100644 server/src/user/user.module 2.ts create mode 100644 server/test/jest-e2e 2.json create mode 100644 server/tsconfig.build 2.json diff --git a/server/.prettierrc 2 b/server/.prettierrc 2 new file mode 100644 index 000000000..dcb72794f --- /dev/null +++ b/server/.prettierrc 2 @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/server/nest-cli 2.json b/server/nest-cli 2.json new file mode 100644 index 000000000..563742eca --- /dev/null +++ b/server/nest-cli 2.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true, + "assets": [ + "../prisma/*", + "./proto/*" + ] + } +} diff --git a/server/src/app.controller 2.ts b/server/src/app.controller 2.ts new file mode 100644 index 000000000..cce879ee6 --- /dev/null +++ b/server/src/app.controller 2.ts @@ -0,0 +1,12 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getHello(): string { + return this.appService.getHello(); + } +} diff --git a/server/src/app.service 2.ts b/server/src/app.service 2.ts new file mode 100644 index 000000000..927d7cca0 --- /dev/null +++ b/server/src/app.service 2.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getHello(): string { + return 'Hello World!'; + } +} diff --git a/server/src/auth/authenticated.guard 2.ts b/server/src/auth/authenticated.guard 2.ts new file mode 100644 index 000000000..0d9bd6bc6 --- /dev/null +++ b/server/src/auth/authenticated.guard 2.ts @@ -0,0 +1,9 @@ +import { ExecutionContext, Injectable, CanActivate } from '@nestjs/common'; + +@Injectable() +export class AuthenticatedGuard implements CanActivate { + async canActivate(context: ExecutionContext) { + const request = context.switchToHttp().getRequest(); + return request.isAuthenticated(); + } +} diff --git a/server/src/auto/auto.module 2.ts b/server/src/auto/auto.module 2.ts new file mode 100644 index 000000000..3335b8aa9 --- /dev/null +++ b/server/src/auto/auto.module 2.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { AutoService } from './auto.service'; +import { AutoController } from './auto.controller'; + +@Module({ + controllers: [AutoController], + providers: [AutoService], +}) +export class AutoModule {} diff --git a/server/src/friend/friend.module 2.ts b/server/src/friend/friend.module 2.ts new file mode 100644 index 000000000..2e5aa94fd --- /dev/null +++ b/server/src/friend/friend.module 2.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { FriendService } from './friend.service'; +import { FriendController } from './friend.controller'; + +@Module({ + providers: [FriendService], + controllers: [FriendController], +}) +export class FriendModule {} diff --git a/server/src/group/group.controller.ts b/server/src/group/group.controller.ts index d383dc51c..5b20ea737 100644 --- a/server/src/group/group.controller.ts +++ b/server/src/group/group.controller.ts @@ -46,7 +46,7 @@ export class GroupController { throw new BadRequestException({ timestamp: new Date().toISOString(), path: `/api/group`, - data: `There was an error creating the group, the error: ${error}`, + data: `There was an error creating the group, the error: ${error.message}`, }); } } diff --git a/server/src/group/group.module 2.ts b/server/src/group/group.module 2.ts new file mode 100644 index 000000000..498d1e7c9 --- /dev/null +++ b/server/src/group/group.module 2.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { GroupService } from './group.service'; +import { GroupController } from './group.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { UserService } from 'src/user/user.service'; + +@Module({ + controllers: [GroupController], + providers: [GroupService, PrismaService, UserService], +}) +export class GroupModule {} diff --git a/server/src/group/group.service.ts b/server/src/group/group.service.ts index bbbdda216..f848394c7 100644 --- a/server/src/group/group.service.ts +++ b/server/src/group/group.service.ts @@ -21,18 +21,18 @@ export class GroupService { private readonly user: UserService, ) {} - async create(createGroupDto: CreateGroupDto) { + async create(createGroupDto: CreateGroupDto): Promise { const { name, timetableIDs, memberIDs, groupAdminIDs, + visibility = 'PRIVATE', description = '', imageURL = '', } = createGroupDto; - const data: any = { name, description, imageURL }; - + const data: any = { name, description, imageURL, visibility }; try { const [timetables, members, admins] = await Promise.all([ this.user.getTimetablesByIDs(timetableIDs), @@ -58,8 +58,7 @@ export class GroupService { }; } - const group = await this.prisma.group.create({ data }); - return group; + return Promise.resolve(await this.prisma.group.create({ data })); } catch (error) { if (error.code === PrismaErrorCode.UNIQUE_CONSTRAINT_FAILED) { throw new ConflictException('Group already exists'); diff --git a/server/src/prisma/prisma.module 2.ts b/server/src/prisma/prisma.module 2.ts new file mode 100644 index 000000000..f9deb7f60 --- /dev/null +++ b/server/src/prisma/prisma.module 2.ts @@ -0,0 +1,7 @@ +import { Module } from '@nestjs/common'; +import { PrismaService } from './prisma.service'; + +@Module({ + providers: [PrismaService], +}) +export class PrismaModule {} diff --git a/server/src/prisma/prisma.service 2.ts b/server/src/prisma/prisma.service 2.ts new file mode 100644 index 000000000..e576e1326 --- /dev/null +++ b/server/src/prisma/prisma.service 2.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +// import { PrismaClient } from '@prisma/client'; +const { PrismaClient } = require('@prisma/client'); +import 'dotenv/config'; + +@Injectable() +export class PrismaService extends PrismaClient { + constructor() { + super({ + datasources: { + db: { + url: process.env.DATABASE_URL, + }, + }, + }); + } +} diff --git a/server/src/user/user.module 2.ts b/server/src/user/user.module 2.ts new file mode 100644 index 000000000..1b541b22a --- /dev/null +++ b/server/src/user/user.module 2.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { UserService } from './user.service'; +import { UserController } from './user.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; + +@Module({ + providers: [UserService, PrismaService], + controllers: [UserController], +}) +export class UserModule {} diff --git a/server/test/jest-e2e 2.json b/server/test/jest-e2e 2.json new file mode 100644 index 000000000..e9d912f3e --- /dev/null +++ b/server/test/jest-e2e 2.json @@ -0,0 +1,9 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": ".", + "testEnvironment": "node", + "testRegex": ".e2e-spec.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + } +} diff --git a/server/tsconfig.build 2.json b/server/tsconfig.build 2.json new file mode 100644 index 000000000..64f86c6bd --- /dev/null +++ b/server/tsconfig.build 2.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} From a0c2cf45912bfa8d46fa41117546010041fbf603 Mon Sep 17 00:00:00 2001 From: ray Date: Mon, 27 May 2024 15:54:30 +1000 Subject: [PATCH 49/92] Resolve for promise return creation of groups added --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index 089622d0f..8c94cae4b 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -26,6 +26,7 @@ const AddGroupDialog = () => { const handleCreateGroup = async () => { try { + const res = await fetch(`${API_URL.server}/group`, { method: 'POST', headers: { @@ -35,16 +36,17 @@ const AddGroupDialog = () => { body: JSON.stringify({ name: groupName, visibility: 'PRIVATE', - timetableIDs: ['0', '1', '2'], + timetableIDs: [], memberIDs: selectedFriends.map((friend) => friend.zID), - groupAdmins: ['0'], - groupImageURL: groupImageURL, + groupAdminIDs: [], + imageURL: groupImageURL, }), }); - - if (res.status !== 200) throw new NetworkError("Couldn't get response"); + if (res.status !== 201) throw new NetworkError("Couldn't get response"); + const groupCreationStatus = await res.json(); + console.log(groupCreationStatus); // Can see the status of group creation here! } catch (error) { - throw new NetworkError("Couldn't get response"); + throw new NetworkError(`Couldn't get response cause encountered error: ${error}`); } }; From 01c62978a57d8b590fc96b7d7d6a792f9d05271a Mon Sep 17 00:00:00 2001 From: ray Date: Tue, 28 May 2024 10:55:14 +1000 Subject: [PATCH 50/92] removed the extra files --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 84 ------------------- server/.prettierrc 2 | 4 - server/nest-cli 2.json | 12 --- server/src/app.controller 2.ts | 12 --- server/src/app.service 2.ts | 8 -- server/src/auto/auto.module 2.ts | 9 -- server/src/friend/friend.module 2.ts | 9 -- server/src/group/entities/group.entity.ts | 1 - server/src/group/group.controller.ts | 2 +- server/src/group/group.module 2.ts | 11 --- server/src/prisma/prisma.module 2.ts | 7 -- server/src/prisma/prisma.service 2.ts | 17 ---- server/src/proto/autotimetabler_grpc_pb.d.ts | 2 +- server/src/user/user.module 2.ts | 10 --- server/tsconfig.build 2.json | 4 - 15 files changed, 2 insertions(+), 190 deletions(-) delete mode 100644 client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx delete mode 100644 server/.prettierrc 2 delete mode 100644 server/nest-cli 2.json delete mode 100644 server/src/app.controller 2.ts delete mode 100644 server/src/app.service 2.ts delete mode 100644 server/src/auto/auto.module 2.ts delete mode 100644 server/src/friend/friend.module 2.ts delete mode 100644 server/src/group/entities/group.entity.ts delete mode 100644 server/src/group/group.module 2.ts delete mode 100644 server/src/prisma/prisma.module 2.ts delete mode 100644 server/src/prisma/prisma.service 2.ts delete mode 100644 server/src/user/user.module 2.ts delete mode 100644 server/tsconfig.build 2.json diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx deleted file mode 100644 index 8c94cae4b..000000000 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React, { useState } from 'react'; -import { Add as AddIcon } from '@mui/icons-material'; -import { Dialog, IconButton, Tooltip } from '@mui/material'; -import AddGroupDialogActions from './AddGroupDialogActions'; -import AddGroupDialogTitle from './AddGroupDialogTitle'; -import AddGroupDialogContent from './AddGroupDialogContent'; -import NetworkError from '../../../interfaces/NetworkError'; -import { API_URL } from '../../../api/config'; - -export interface FriendType { - name: string; - zID: string; -} - -export enum Privacy { - PRIVATE = 'private', - PUBLIC = 'public', -} - -const AddGroupDialog = () => { - const [isOpen, setIsOpen] = useState(false); - const [groupName, setGroupName] = useState(''); - const [selectedFriends, setSelectedFriends] = useState([]); - const [groupImageURL, setGroupImageURL] = useState(''); - const [privacy, setPrivacy] = useState(Privacy.PRIVATE); - - const handleCreateGroup = async () => { - try { - - const res = await fetch(`${API_URL.server}/group`, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - name: groupName, - visibility: 'PRIVATE', - timetableIDs: [], - memberIDs: selectedFriends.map((friend) => friend.zID), - groupAdminIDs: [], - imageURL: groupImageURL, - }), - }); - if (res.status !== 201) throw new NetworkError("Couldn't get response"); - const groupCreationStatus = await res.json(); - console.log(groupCreationStatus); // Can see the status of group creation here! - } catch (error) { - throw new NetworkError(`Couldn't get response cause encountered error: ${error}`); - } - }; - - const handleClose = () => { - setIsOpen(false); - setGroupName(''); - setSelectedFriends([]); - setGroupImageURL(''); - }; - - return ( - <> - - setIsOpen(true)}> - - - - - - - - - - - ); -}; - -export default AddGroupDialog; diff --git a/server/.prettierrc 2 b/server/.prettierrc 2 deleted file mode 100644 index dcb72794f..000000000 --- a/server/.prettierrc 2 +++ /dev/null @@ -1,4 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "all" -} \ No newline at end of file diff --git a/server/nest-cli 2.json b/server/nest-cli 2.json deleted file mode 100644 index 563742eca..000000000 --- a/server/nest-cli 2.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/nest-cli", - "collection": "@nestjs/schematics", - "sourceRoot": "src", - "compilerOptions": { - "deleteOutDir": true, - "assets": [ - "../prisma/*", - "./proto/*" - ] - } -} diff --git a/server/src/app.controller 2.ts b/server/src/app.controller 2.ts deleted file mode 100644 index cce879ee6..000000000 --- a/server/src/app.controller 2.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Controller, Get } from '@nestjs/common'; -import { AppService } from './app.service'; - -@Controller() -export class AppController { - constructor(private readonly appService: AppService) {} - - @Get() - getHello(): string { - return this.appService.getHello(); - } -} diff --git a/server/src/app.service 2.ts b/server/src/app.service 2.ts deleted file mode 100644 index 927d7cca0..000000000 --- a/server/src/app.service 2.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -@Injectable() -export class AppService { - getHello(): string { - return 'Hello World!'; - } -} diff --git a/server/src/auto/auto.module 2.ts b/server/src/auto/auto.module 2.ts deleted file mode 100644 index 3335b8aa9..000000000 --- a/server/src/auto/auto.module 2.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Module } from '@nestjs/common'; -import { AutoService } from './auto.service'; -import { AutoController } from './auto.controller'; - -@Module({ - controllers: [AutoController], - providers: [AutoService], -}) -export class AutoModule {} diff --git a/server/src/friend/friend.module 2.ts b/server/src/friend/friend.module 2.ts deleted file mode 100644 index 2e5aa94fd..000000000 --- a/server/src/friend/friend.module 2.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Module } from '@nestjs/common'; -import { FriendService } from './friend.service'; -import { FriendController } from './friend.controller'; - -@Module({ - providers: [FriendService], - controllers: [FriendController], -}) -export class FriendModule {} diff --git a/server/src/group/entities/group.entity.ts b/server/src/group/entities/group.entity.ts deleted file mode 100644 index f08776497..000000000 --- a/server/src/group/entities/group.entity.ts +++ /dev/null @@ -1 +0,0 @@ -export class Group {} diff --git a/server/src/group/group.controller.ts b/server/src/group/group.controller.ts index 5b20ea737..d383dc51c 100644 --- a/server/src/group/group.controller.ts +++ b/server/src/group/group.controller.ts @@ -46,7 +46,7 @@ export class GroupController { throw new BadRequestException({ timestamp: new Date().toISOString(), path: `/api/group`, - data: `There was an error creating the group, the error: ${error.message}`, + data: `There was an error creating the group, the error: ${error}`, }); } } diff --git a/server/src/group/group.module 2.ts b/server/src/group/group.module 2.ts deleted file mode 100644 index 498d1e7c9..000000000 --- a/server/src/group/group.module 2.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; -import { GroupService } from './group.service'; -import { GroupController } from './group.controller'; -import { PrismaService } from 'src/prisma/prisma.service'; -import { UserService } from 'src/user/user.service'; - -@Module({ - controllers: [GroupController], - providers: [GroupService, PrismaService, UserService], -}) -export class GroupModule {} diff --git a/server/src/prisma/prisma.module 2.ts b/server/src/prisma/prisma.module 2.ts deleted file mode 100644 index f9deb7f60..000000000 --- a/server/src/prisma/prisma.module 2.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Module } from '@nestjs/common'; -import { PrismaService } from './prisma.service'; - -@Module({ - providers: [PrismaService], -}) -export class PrismaModule {} diff --git a/server/src/prisma/prisma.service 2.ts b/server/src/prisma/prisma.service 2.ts deleted file mode 100644 index e576e1326..000000000 --- a/server/src/prisma/prisma.service 2.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Injectable } from '@nestjs/common'; -// import { PrismaClient } from '@prisma/client'; -const { PrismaClient } = require('@prisma/client'); -import 'dotenv/config'; - -@Injectable() -export class PrismaService extends PrismaClient { - constructor() { - super({ - datasources: { - db: { - url: process.env.DATABASE_URL, - }, - }, - }); - } -} diff --git a/server/src/proto/autotimetabler_grpc_pb.d.ts b/server/src/proto/autotimetabler_grpc_pb.d.ts index 6c2cd086a..02fc10520 100644 --- a/server/src/proto/autotimetabler_grpc_pb.d.ts +++ b/server/src/proto/autotimetabler_grpc_pb.d.ts @@ -95,4 +95,4 @@ export class AutoTimetablerClient response: autotimetabler_pb.AutoTimetableResponse, ) => void, ): grpc.ClientUnaryCall; -} \ No newline at end of file +} diff --git a/server/src/user/user.module 2.ts b/server/src/user/user.module 2.ts deleted file mode 100644 index 1b541b22a..000000000 --- a/server/src/user/user.module 2.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Module } from '@nestjs/common'; -import { UserService } from './user.service'; -import { UserController } from './user.controller'; -import { PrismaService } from 'src/prisma/prisma.service'; - -@Module({ - providers: [UserService, PrismaService], - controllers: [UserController], -}) -export class UserModule {} diff --git a/server/tsconfig.build 2.json b/server/tsconfig.build 2.json deleted file mode 100644 index 64f86c6bd..000000000 --- a/server/tsconfig.build 2.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "./tsconfig.json", - "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] -} From af4432f6568cdf94d9ace40c55de42b3e732259b Mon Sep 17 00:00:00 2001 From: ray Date: Tue, 28 May 2024 10:58:05 +1000 Subject: [PATCH 51/92] added the group dialog file again --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx new file mode 100644 index 000000000..857d84e16 --- /dev/null +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -0,0 +1,84 @@ +import React, { useState } from 'react'; +import { Add as AddIcon } from '@mui/icons-material'; +import { Dialog, IconButton, Tooltip } from '@mui/material'; +import AddGroupDialogActions from './AddGroupDialogActions'; +import AddGroupDialogTitle from './AddGroupDialogTitle'; +import AddGroupDialogContent from './AddGroupDialogContent'; +import NetworkError from '../../../interfaces/NetworkError'; +import { API_URL } from '../../../api/config'; + +export interface FriendType { + name: string; + zID: string; +} + +export enum Privacy { + PRIVATE = 'private', + PUBLIC = 'public', +} + +const AddGroupDialog = () => { + const [isOpen, setIsOpen] = useState(false); + const [groupName, setGroupName] = useState(''); + const [selectedFriends, setSelectedFriends] = useState([]); + const [groupImageURL, setGroupImageURL] = useState(''); + const [privacy, setPrivacy] = useState(Privacy.PRIVATE); + + const handleCreateGroup = async () => { + try { + + const res = await fetch(`${API_URL.server}/group`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: groupName, + visibility: 'PRIVATE', + timetableIDs: [], + memberIDs: selectedFriends.map((friend) => friend.zID), + groupAdminIDs: [], + imageURL: groupImageURL, + }), + }); + if (res.status !== 201) throw new NetworkError("Couldn't get response"); + const groupCreationStatus = await res.json(); + console.log(groupCreationStatus); // Can see the status of group creation here! + } catch (error) { + throw new NetworkError(`Couldn't get response cause encountered error: ${error}`); + } + }; + + const handleClose = () => { + setIsOpen(false); + setGroupName(''); + setSelectedFriends([]); + setGroupImageURL(''); + }; + + return ( + <> + + setIsOpen(true)}> + + + + + + + + + + + ); +}; + +export default AddGroupDialog; \ No newline at end of file From 3aafd2614d2d4f27235eb35863779b6498d9d76b Mon Sep 17 00:00:00 2001 From: ray Date: Tue, 28 May 2024 13:42:28 +1000 Subject: [PATCH 52/92] testing new deletions --- server/prisma/prisma-error-codes.enum.ts | 4 ++++ server/src/auth/authenticated.guard 2.ts | 9 --------- server/src/group/entities/group.entity.ts | 1 + server/test/jest-e2e 2.json | 9 --------- 4 files changed, 5 insertions(+), 18 deletions(-) create mode 100644 server/prisma/prisma-error-codes.enum.ts delete mode 100644 server/src/auth/authenticated.guard 2.ts create mode 100644 server/src/group/entities/group.entity.ts delete mode 100644 server/test/jest-e2e 2.json diff --git a/server/prisma/prisma-error-codes.enum.ts b/server/prisma/prisma-error-codes.enum.ts new file mode 100644 index 000000000..851fa1c93 --- /dev/null +++ b/server/prisma/prisma-error-codes.enum.ts @@ -0,0 +1,4 @@ +export enum PrismaErrorCode { + UNIQUE_CONSTRAINT_FAILED = 'P2002', + RECORD_NOT_FOUND = 'P2025', +} diff --git a/server/src/auth/authenticated.guard 2.ts b/server/src/auth/authenticated.guard 2.ts deleted file mode 100644 index 0d9bd6bc6..000000000 --- a/server/src/auth/authenticated.guard 2.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ExecutionContext, Injectable, CanActivate } from '@nestjs/common'; - -@Injectable() -export class AuthenticatedGuard implements CanActivate { - async canActivate(context: ExecutionContext) { - const request = context.switchToHttp().getRequest(); - return request.isAuthenticated(); - } -} diff --git a/server/src/group/entities/group.entity.ts b/server/src/group/entities/group.entity.ts new file mode 100644 index 000000000..f08776497 --- /dev/null +++ b/server/src/group/entities/group.entity.ts @@ -0,0 +1 @@ +export class Group {} diff --git a/server/test/jest-e2e 2.json b/server/test/jest-e2e 2.json deleted file mode 100644 index e9d912f3e..000000000 --- a/server/test/jest-e2e 2.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -} From e6d1a4856fa6ab8721fa006677661a62d15d6aab Mon Sep 17 00:00:00 2001 From: ray Date: Tue, 28 May 2024 14:00:12 +1000 Subject: [PATCH 53/92] moved prisma stuff to its own separate folder --- server/{ => src}/prisma/prisma-error-codes.enum.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename server/{ => src}/prisma/prisma-error-codes.enum.ts (100%) diff --git a/server/prisma/prisma-error-codes.enum.ts b/server/src/prisma/prisma-error-codes.enum.ts similarity index 100% rename from server/prisma/prisma-error-codes.enum.ts rename to server/src/prisma/prisma-error-codes.enum.ts From d3f5a660a90cdf25d87b3135df7bdf82c8b41c11 Mon Sep 17 00:00:00 2001 From: ray Date: Tue, 28 May 2024 15:47:23 +1000 Subject: [PATCH 54/92] changed around server files --- server/Dockerfile | 2 +- server/prisma/prisma-error-codes.enum.ts | 4 ++++ server/src/group/group.service.ts | 15 ++++++--------- 3 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 server/prisma/prisma-error-codes.enum.ts diff --git a/server/Dockerfile b/server/Dockerfile index 49dcdefed..a70f58e0b 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -25,4 +25,4 @@ RUN npx prisma generate EXPOSE 3001 -CMD ["pnpm", "run", "start:migrate:prod"] \ No newline at end of file +CMD ["pnpm", "run", "start:migrate:prod"] diff --git a/server/prisma/prisma-error-codes.enum.ts b/server/prisma/prisma-error-codes.enum.ts new file mode 100644 index 000000000..851fa1c93 --- /dev/null +++ b/server/prisma/prisma-error-codes.enum.ts @@ -0,0 +1,4 @@ +export enum PrismaErrorCode { + UNIQUE_CONSTRAINT_FAILED = 'P2002', + RECORD_NOT_FOUND = 'P2025', +} diff --git a/server/src/group/group.service.ts b/server/src/group/group.service.ts index f848394c7..22a13efb1 100644 --- a/server/src/group/group.service.ts +++ b/server/src/group/group.service.ts @@ -8,11 +8,7 @@ import { PrismaService } from '../prisma/prisma.service'; import { CreateGroupDto } from './dto/create-group.dto'; import { UpdateGroupDto } from './dto/update-group.dto'; import { UserService } from 'src/user/user.service'; - -export enum PrismaErrorCode { - UNIQUE_CONSTRAINT_FAILED = 'P2002', - RECORD_NOT_FOUND = 'P2025', -} +import { PrismaErrorCode } from 'prisma/prisma-error-codes.enum'; @Injectable() export class GroupService { @@ -21,18 +17,18 @@ export class GroupService { private readonly user: UserService, ) {} - async create(createGroupDto: CreateGroupDto): Promise { + async create(createGroupDto: CreateGroupDto) { const { name, timetableIDs, memberIDs, groupAdminIDs, - visibility = 'PRIVATE', description = '', imageURL = '', } = createGroupDto; - const data: any = { name, description, imageURL, visibility }; + const data: any = { name, description, imageURL }; + try { const [timetables, members, admins] = await Promise.all([ this.user.getTimetablesByIDs(timetableIDs), @@ -58,7 +54,8 @@ export class GroupService { }; } - return Promise.resolve(await this.prisma.group.create({ data })); + const group = await this.prisma.group.create({ data }); + return group; } catch (error) { if (error.code === PrismaErrorCode.UNIQUE_CONSTRAINT_FAILED) { throw new ConflictException('Group already exists'); From 446b15c1acbd01d3aaa68ae0b76cf18c59ee832c Mon Sep 17 00:00:00 2001 From: ray Date: Tue, 28 May 2024 15:53:15 +1000 Subject: [PATCH 55/92] cleaned up service --- server/prisma/prisma-error-codes.enum.ts | 4 ---- server/src/group/group.service.ts | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 server/prisma/prisma-error-codes.enum.ts diff --git a/server/prisma/prisma-error-codes.enum.ts b/server/prisma/prisma-error-codes.enum.ts deleted file mode 100644 index 851fa1c93..000000000 --- a/server/prisma/prisma-error-codes.enum.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum PrismaErrorCode { - UNIQUE_CONSTRAINT_FAILED = 'P2002', - RECORD_NOT_FOUND = 'P2025', -} diff --git a/server/src/group/group.service.ts b/server/src/group/group.service.ts index 22a13efb1..f5c2bcf3b 100644 --- a/server/src/group/group.service.ts +++ b/server/src/group/group.service.ts @@ -8,7 +8,7 @@ import { PrismaService } from '../prisma/prisma.service'; import { CreateGroupDto } from './dto/create-group.dto'; import { UpdateGroupDto } from './dto/update-group.dto'; import { UserService } from 'src/user/user.service'; -import { PrismaErrorCode } from 'prisma/prisma-error-codes.enum'; +import { PrismaErrorCode } from 'src/prisma/prisma-error-codes.enum'; @Injectable() export class GroupService { From 6d6c53651b26356919db98031c7561071d6d73e8 Mon Sep 17 00:00:00 2001 From: ray Date: Fri, 31 May 2024 21:57:20 +1000 Subject: [PATCH 56/92] new models --- .../migrations/20240526045449_/migration.sql | 86 ------- .../20240531115703_init/migration.sql | 220 ++++++++++++++++++ 2 files changed, 220 insertions(+), 86 deletions(-) delete mode 100644 server/prisma/migrations/20240526045449_/migration.sql create mode 100644 server/prisma/migrations/20240531115703_init/migration.sql diff --git a/server/prisma/migrations/20240526045449_/migration.sql b/server/prisma/migrations/20240526045449_/migration.sql deleted file mode 100644 index 16374c60a..000000000 --- a/server/prisma/migrations/20240526045449_/migration.sql +++ /dev/null @@ -1,86 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `userId` on the `settings` table. All the data in the column will be lost. - - You are about to drop the column `userId` on the `timetables` table. All the data in the column will be lost. - - The primary key for the `users` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `userId` on the `users` table. All the data in the column will be lost. - - A unique constraint covering the columns `[userID]` on the table `settings` will be added. If there are existing duplicate values, this will fail. - - Added the required column `userID` to the `settings` table without a default value. This is not possible if the table is not empty. - - Added the required column `userID` to the `timetables` table without a default value. This is not possible if the table is not empty. - - Added the required column `userID` to the `users` table without a default value. This is not possible if the table is not empty. - -*/ --- DropForeignKey -ALTER TABLE "_TimetableToUser" DROP CONSTRAINT "_TimetableToUser_B_fkey"; - --- DropForeignKey -ALTER TABLE "_admins" DROP CONSTRAINT "_admins_B_fkey"; - --- DropForeignKey -ALTER TABLE "_friend_requests" DROP CONSTRAINT "_friend_requests_A_fkey"; - --- DropForeignKey -ALTER TABLE "_friend_requests" DROP CONSTRAINT "_friend_requests_B_fkey"; - --- DropForeignKey -ALTER TABLE "_group_members" DROP CONSTRAINT "_group_members_B_fkey"; - --- DropForeignKey -ALTER TABLE "_user_friends" DROP CONSTRAINT "_user_friends_A_fkey"; - --- DropForeignKey -ALTER TABLE "_user_friends" DROP CONSTRAINT "_user_friends_B_fkey"; - --- DropForeignKey -ALTER TABLE "settings" DROP CONSTRAINT "settings_userId_fkey"; - --- DropIndex -DROP INDEX "settings_userId_key"; - --- DropIndex -DROP INDEX "users_userId_idx"; - --- AlterTable -ALTER TABLE "settings" DROP COLUMN "userId", -ADD COLUMN "userID" TEXT NOT NULL; - --- AlterTable -ALTER TABLE "timetables" DROP COLUMN "userId", -ADD COLUMN "userID" TEXT NOT NULL; - --- AlterTable -ALTER TABLE "users" DROP CONSTRAINT "users_pkey", -DROP COLUMN "userId", -ADD COLUMN "userID" TEXT NOT NULL, -ADD CONSTRAINT "users_pkey" PRIMARY KEY ("userID"); - --- CreateIndex -CREATE UNIQUE INDEX "settings_userID_key" ON "settings"("userID"); - --- CreateIndex -CREATE INDEX "users_userID_idx" ON "users"("userID"); - --- AddForeignKey -ALTER TABLE "settings" ADD CONSTRAINT "settings_userID_fkey" FOREIGN KEY ("userID") REFERENCES "users"("userID") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_user_friends" ADD CONSTRAINT "_user_friends_A_fkey" FOREIGN KEY ("A") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_user_friends" ADD CONSTRAINT "_user_friends_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_friend_requests" ADD CONSTRAINT "_friend_requests_A_fkey" FOREIGN KEY ("A") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_friend_requests" ADD CONSTRAINT "_friend_requests_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_group_members" ADD CONSTRAINT "_group_members_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_admins" ADD CONSTRAINT "_admins_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_TimetableToUser" ADD CONSTRAINT "_TimetableToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/prisma/migrations/20240531115703_init/migration.sql b/server/prisma/migrations/20240531115703_init/migration.sql new file mode 100644 index 000000000..cad907e66 --- /dev/null +++ b/server/prisma/migrations/20240531115703_init/migration.sql @@ -0,0 +1,220 @@ +-- CreateEnum +CREATE TYPE "group_visibility" AS ENUM ('PUBLIC', 'PRIVATE'); + +-- CreateEnum +CREATE TYPE "ClassType" AS ENUM ('LECTURE', 'TUTORIAL', 'LAORATORY', 'OTHER'); + +-- CreateTable +CREATE TABLE "users" ( + "userID" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "lastLogin" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP, + "firstname" TEXT, + "lastname" TEXT, + "email" TEXT NOT NULL, + "profileURL" TEXT, + + CONSTRAINT "users_pkey" PRIMARY KEY ("userID") +); + +-- CreateTable +CREATE TABLE "groups" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "imageURL" TEXT, + "visibility" "group_visibility" NOT NULL DEFAULT 'PRIVATE', + + CONSTRAINT "groups_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "events" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "location" TEXT, + "description" TEXT, + "colour" TEXT NOT NULL DEFAULT '#1F7E8C', + "day" TEXT NOT NULL, + "start" TIMESTAMP(3) NOT NULL, + "end" TIMESTAMP(3) NOT NULL, + "timetableId" TEXT, + "groupIds" TEXT[], + + CONSTRAINT "events_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "classes" ( + "id" TEXT NOT NULL, + "classType" "ClassType" NOT NULL, + "courseName" TEXT, + "timetableId" TEXT +); + +-- CreateTable +CREATE TABLE "timetables" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "selectedCourses" TEXT[], + "userID" TEXT NOT NULL, + + CONSTRAINT "timetables_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "settings" ( + "userID" TEXT NOT NULL, + "is12HourMode" BOOLEAN NOT NULL, + "isDarkMode" BOOLEAN NOT NULL, + "isSquareEdges" BOOLEAN NOT NULL, + "isHideFullClasses" BOOLEAN NOT NULL, + "isDefaultUnscheduled" BOOLEAN NOT NULL, + "isHideClassInfo" BOOLEAN NOT NULL, + "isSortAlphabetic" BOOLEAN NOT NULL, + "isShowOnlyOpenClasses" BOOLEAN NOT NULL, + "isHideExamClasses" BOOLEAN NOT NULL, + "isConvertToLocalTimezone" BOOLEAN NOT NULL +); + +-- CreateTable +CREATE TABLE "sessions" ( + "id" TEXT NOT NULL, + "sid" TEXT NOT NULL, + "data" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "sessions_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_user_friends" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_friend_requests" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_group_timetables" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_group_members" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_admins" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_TimetableToUser" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE INDEX "users_userID_idx" ON "users"("userID"); + +-- CreateIndex +CREATE UNIQUE INDEX "classes_id_key" ON "classes"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "timetables_id_key" ON "timetables"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "settings_userID_key" ON "settings"("userID"); + +-- CreateIndex +CREATE UNIQUE INDEX "sessions_sid_key" ON "sessions"("sid"); + +-- CreateIndex +CREATE UNIQUE INDEX "_user_friends_AB_unique" ON "_user_friends"("A", "B"); + +-- CreateIndex +CREATE INDEX "_user_friends_B_index" ON "_user_friends"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_friend_requests_AB_unique" ON "_friend_requests"("A", "B"); + +-- CreateIndex +CREATE INDEX "_friend_requests_B_index" ON "_friend_requests"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_group_timetables_AB_unique" ON "_group_timetables"("A", "B"); + +-- CreateIndex +CREATE INDEX "_group_timetables_B_index" ON "_group_timetables"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_group_members_AB_unique" ON "_group_members"("A", "B"); + +-- CreateIndex +CREATE INDEX "_group_members_B_index" ON "_group_members"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_admins_AB_unique" ON "_admins"("A", "B"); + +-- CreateIndex +CREATE INDEX "_admins_B_index" ON "_admins"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_TimetableToUser_AB_unique" ON "_TimetableToUser"("A", "B"); + +-- CreateIndex +CREATE INDEX "_TimetableToUser_B_index" ON "_TimetableToUser"("B"); + +-- AddForeignKey +ALTER TABLE "events" ADD CONSTRAINT "events_timetableId_fkey" FOREIGN KEY ("timetableId") REFERENCES "timetables"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "classes" ADD CONSTRAINT "classes_timetableId_fkey" FOREIGN KEY ("timetableId") REFERENCES "timetables"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "settings" ADD CONSTRAINT "settings_userID_fkey" FOREIGN KEY ("userID") REFERENCES "users"("userID") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_user_friends" ADD CONSTRAINT "_user_friends_A_fkey" FOREIGN KEY ("A") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_user_friends" ADD CONSTRAINT "_user_friends_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_friend_requests" ADD CONSTRAINT "_friend_requests_A_fkey" FOREIGN KEY ("A") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_friend_requests" ADD CONSTRAINT "_friend_requests_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_group_timetables" ADD CONSTRAINT "_group_timetables_A_fkey" FOREIGN KEY ("A") REFERENCES "groups"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_group_timetables" ADD CONSTRAINT "_group_timetables_B_fkey" FOREIGN KEY ("B") REFERENCES "timetables"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_group_members" ADD CONSTRAINT "_group_members_A_fkey" FOREIGN KEY ("A") REFERENCES "groups"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_group_members" ADD CONSTRAINT "_group_members_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_admins" ADD CONSTRAINT "_admins_A_fkey" FOREIGN KEY ("A") REFERENCES "groups"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_admins" ADD CONSTRAINT "_admins_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_TimetableToUser" ADD CONSTRAINT "_TimetableToUser_A_fkey" FOREIGN KEY ("A") REFERENCES "timetables"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_TimetableToUser" ADD CONSTRAINT "_TimetableToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "users"("userID") ON DELETE CASCADE ON UPDATE CASCADE; From d3dd5b18fd861bc142fbdb16f77f42b5cf6551cb Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Sat, 1 Jun 2024 09:45:52 +1000 Subject: [PATCH 57/92] placeholder for getGroups function when a new group is created --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 8 +++++- .../sidebar/groupsSideBar/GroupsSidebar.tsx | 27 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index 581a5fe4f..f3506d76f 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -17,7 +17,11 @@ export enum Privacy { PUBLIC = 'public', } -const AddGroupDialog = () => { +interface AddGroupDialogProps { + getGroups: () => void; +} + +const AddGroupDialog: React.FC = ({ getGroups }) => { const [isOpen, setIsOpen] = useState(false); const [groupName, setGroupName] = useState(''); const [selectedFriends, setSelectedFriends] = useState([]); @@ -41,7 +45,9 @@ const AddGroupDialog = () => { imageURL: groupImageURL, }), }); + if (res.status === 201) getGroups(); if (res.status !== 201) throw new NetworkError("Couldn't get response"); + const groupCreationStatus = await res.json(); console.log(groupCreationStatus); // Can see the status of group creation here! } catch (error) { diff --git a/client/src/components/sidebar/groupsSideBar/GroupsSidebar.tsx b/client/src/components/sidebar/groupsSideBar/GroupsSidebar.tsx index e0cb3fdba..9ac2ead24 100644 --- a/client/src/components/sidebar/groupsSideBar/GroupsSidebar.tsx +++ b/client/src/components/sidebar/groupsSideBar/GroupsSidebar.tsx @@ -4,6 +4,8 @@ import React, { useState } from 'react'; import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd'; import { DummyGroupData } from './dummyData'; import AddGroupDialog from '../addGroupDialog/AddGroupDialog'; +import { API_URL } from '../../../api/config'; +import NetworkError from '../../../interfaces/NetworkError'; const GROUP_CIRCLE_SIZE = 65; @@ -40,6 +42,29 @@ const StyledContainer = styled('div')` const GroupsSidebar = () => { const [items, setItems] = useState(DummyGroupData); + const getGroups = async () => { + console.log('fetching groups...'); + return; + + try { + const res = await fetch(`${API_URL.server}/user/group/:zid`, { //TODO fetch zid + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + }); + + if (res.status !== 201) throw new NetworkError("Couldn't get response"); + + const getGroupStatus = await res.json(); + console.log(getGroupStatus); + + } catch (error) { + throw new NetworkError(`Couldn't get response cause encountered error: ${error}`); + } + } + // Reorders the given list by moving the value at startIndex to endIndex. const reorder = (list: any, startIndex: number, endIndex: number) => { const result = Array.from(list); @@ -81,7 +106,7 @@ const GroupsSidebar = () => { ))} {provided.placeholder} - + )} From 209e91b13549dd01b9f00069a3e4300d5ddec595 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Sat, 1 Jun 2024 10:02:59 +1000 Subject: [PATCH 58/92] added notangles logo as the default image for creating a new group --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 19 +++++++++++++++---- .../addGroupDialog/AddGroupDialogContent.tsx | 7 ------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index f3506d76f..b6f86d153 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -6,6 +6,7 @@ import AddGroupDialogTitle from './AddGroupDialogTitle'; import AddGroupDialogContent from './AddGroupDialogContent'; import NetworkError from '../../../interfaces/NetworkError'; import { API_URL } from '../../../api/config'; +import NotanglesLogo from '../../../assets/notangles_1.png'; export interface FriendType { name: string; @@ -25,10 +26,16 @@ const AddGroupDialog: React.FC = ({ getGroups }) => { const [isOpen, setIsOpen] = useState(false); const [groupName, setGroupName] = useState(''); const [selectedFriends, setSelectedFriends] = useState([]); - const [groupImageURL, setGroupImageURL] = useState(''); + const [groupImageURL, setGroupImageURL] = useState(NotanglesLogo); const [privacy, setPrivacy] = useState(Privacy.PRIVATE); + const isCorrectInputs = () => { + return groupName && selectedFriends.length; + }; + const handleCreateGroup = async () => { + if (!isCorrectInputs) return; + try { const res = await fetch(`${API_URL.server}/group`, { method: 'POST', @@ -45,11 +52,15 @@ const AddGroupDialog: React.FC = ({ getGroups }) => { imageURL: groupImageURL, }), }); - if (res.status === 201) getGroups(); - if (res.status !== 201) throw new NetworkError("Couldn't get response"); - const groupCreationStatus = await res.json(); console.log(groupCreationStatus); // Can see the status of group creation here! + + if (res.status === 201) { + getGroups(); + handleClose(); + } else { + throw new NetworkError("Couldn't get response"); + } } catch (error) { throw new NetworkError(`Couldn't get response cause encountered error: ${error}`); } diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx index 4f9db9070..de5c2ec29 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx @@ -37,13 +37,6 @@ const StyledUploadImageContainer = styled('div')` align-items: flex-end; `; -const StyledPrivacyContainer = styled('div')` - display: flex; - align-items: center; - width: 94%; - justify-content: space-between; -`; - interface AddGroupDialogContentProps { groupImageURL: string; setGroupImageURL: (url: string) => void; From ca1d37b642c69041c86a3475b0a3b850b5469977 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Sat, 1 Jun 2024 10:04:19 +1000 Subject: [PATCH 59/92] fixed handleclose for resetting group image --- client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index b6f86d153..c4ee81db3 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -70,7 +70,7 @@ const AddGroupDialog: React.FC = ({ getGroups }) => { setIsOpen(false); setGroupName(''); setSelectedFriends([]); - setGroupImageURL(''); + setGroupImageURL(NotanglesLogo); }; return ( From d8ee887550bd773b2fbc12fe830ee451d76d13e5 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Sun, 2 Jun 2024 21:21:36 +1000 Subject: [PATCH 60/92] disabled create button when input is invalid and display red error after user has interacted with the inputs --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 9 ++++- .../addGroupDialog/AddGroupDialogActions.tsx | 17 ++++++-- .../addGroupDialog/AddGroupDialogContent.tsx | 40 +++++++++++++++++-- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index c4ee81db3..4f304c4a3 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -86,12 +86,19 @@ const AddGroupDialog: React.FC = ({ getGroups }) => { - + ); diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx index 8bfbf81c4..e235ef715 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Button, DialogActions } from '@mui/material'; import { styled } from '@mui/system'; - +import { FriendType } from './AddGroupDialog'; const StyledDialogActions = styled(DialogActions)` background-color: ${({ theme }) => theme.palette.background.paper}; @@ -11,15 +11,26 @@ const StyledDialogActions = styled(DialogActions)` interface AddGroupDialogActionsProps { handleClose: () => void; handleCreateGroup: () => void; + groupName: string; + selectedFriends: FriendType[]; } -const AddGroupDialogActions: React.FC = ({ handleClose, handleCreateGroup }) => { +const AddGroupDialogActions: React.FC = ({ + handleClose, + handleCreateGroup, + groupName, + selectedFriends, +}) => { return ( - diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx index de5c2ec29..2c2fed86e 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogContent.tsx @@ -1,6 +1,18 @@ -import React from 'react'; +import React, { useState } from 'react'; import { CheckCircle as CheckCircleIcon, RadioButtonUnchecked as RadioButtonUncheckedIcon } from '@mui/icons-material'; -import { Autocomplete, Checkbox, Chip, DialogContent, FormControl, InputLabel, MenuItem, Select, Switch, TextField, Tooltip } from '@mui/material'; +import { + Autocomplete, + Checkbox, + Chip, + DialogContent, + FormControl, + InputLabel, + MenuItem, + Select, + Switch, + TextField, + Tooltip, +} from '@mui/material'; import { styled } from '@mui/system'; import EditImagePopOver from './EditImagePopOver'; import { friends } from './dummyData'; @@ -40,7 +52,9 @@ const StyledUploadImageContainer = styled('div')` interface AddGroupDialogContentProps { groupImageURL: string; setGroupImageURL: (url: string) => void; + groupName: string; setGroupName: (groupName: string) => void; + selectedFriends: FriendType[]; setSelectedFriends: (friends: FriendType[]) => void; privacy: Privacy; setPrivacy: (privacy: Privacy) => void; @@ -49,11 +63,17 @@ interface AddGroupDialogContentProps { const AddGroupDialogContent: React.FC = ({ groupImageURL, setGroupImageURL, + groupName, setGroupName, + selectedFriends, setSelectedFriends, privacy, - setPrivacy + setPrivacy, }) => { + // To show red error only after user has interacted with the inputs. + const [isGroupNameInteracted, setGroupNameInteracted] = useState(false); + const [isGroupMemberInteracted, setGroupMemberInteracted] = useState(false); + return ( @@ -69,6 +89,9 @@ const AddGroupDialogContent: React.FC = ({ required fullWidth onChange={(e) => setGroupName(e.target.value)} + onBlur={() => setGroupNameInteracted(true)} + error={groupName === '' && isGroupNameInteracted} + helperText="Must be at least one character" /> = ({ disableCloseOnSelect fullWidth onChange={(_, value) => setSelectedFriends(value)} + onBlur={(e) => setGroupMemberInteracted(true)} getOptionLabel={(option) => option.name} renderOption={(props, option, { selected }) => (
  • @@ -96,7 +120,15 @@ const AddGroupDialogContent: React.FC = ({ )); }} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> From ea623101fa838ca8d921b67ee58dbefbcc075192 Mon Sep 17 00:00:00 2001 From: Jasmine Tran Date: Thu, 6 Jun 2024 15:00:29 +1000 Subject: [PATCH 61/92] refactored group object --- .../sidebar/addGroupDialog/AddGroupDialog.tsx | 59 ++++++++----------- .../addGroupDialog/AddGroupDialogActions.tsx | 10 ++-- .../addGroupDialog/AddGroupDialogContent.tsx | 44 +++++--------- .../addGroupDialog/AddGroupDialogTitle.tsx | 1 - .../addGroupDialog/EditImagePopOver.tsx | 11 ++-- .../sidebar/addGroupDialog/dummyData.tsx | 5 +- 6 files changed, 52 insertions(+), 78 deletions(-) diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx index 4f304c4a3..be8fc2a13 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialog.tsx @@ -8,7 +8,7 @@ import NetworkError from '../../../interfaces/NetworkError'; import { API_URL } from '../../../api/config'; import NotanglesLogo from '../../../assets/notangles_1.png'; -export interface FriendType { +export interface MemberType { name: string; zID: string; } @@ -22,20 +22,24 @@ interface AddGroupDialogProps { getGroups: () => void; } +export interface Group { + name: string; + members: MemberType[]; + imageURL: string; + privacy: Privacy; +} + const AddGroupDialog: React.FC = ({ getGroups }) => { const [isOpen, setIsOpen] = useState(false); - const [groupName, setGroupName] = useState(''); - const [selectedFriends, setSelectedFriends] = useState([]); - const [groupImageURL, setGroupImageURL] = useState(NotanglesLogo); - const [privacy, setPrivacy] = useState(Privacy.PRIVATE); - const isCorrectInputs = () => { - return groupName && selectedFriends.length; - }; + const [group, setGroup] = useState({ + name: '', + members: [], + imageURL: NotanglesLogo, + privacy: Privacy.PRIVATE, + }); const handleCreateGroup = async () => { - if (!isCorrectInputs) return; - try { const res = await fetch(`${API_URL.server}/group`, { method: 'POST', @@ -44,12 +48,12 @@ const AddGroupDialog: React.FC = ({ getGroups }) => { 'Content-Type': 'application/json', }, body: JSON.stringify({ - name: groupName, - visibility: 'PRIVATE', + name: group.name, + visibility: group.privacy, timetableIDs: [], - memberIDs: selectedFriends.map((friend) => friend.zID), + memberIDs: group.members.map((member) => member.zID), groupAdminIDs: [], - imageURL: groupImageURL, + imageURL: group.imageURL, }), }); const groupCreationStatus = await res.json(); @@ -68,9 +72,12 @@ const AddGroupDialog: React.FC = ({ getGroups }) => { const handleClose = () => { setIsOpen(false); - setGroupName(''); - setSelectedFriends([]); - setGroupImageURL(NotanglesLogo); + updateFormState({ + name: '', + members: [], + imageURL: NotanglesLogo, + privacy: Privacy.PRIVATE, + }); }; return ( @@ -83,22 +90,8 @@ const AddGroupDialog: React.FC = ({ getGroups }) => { - - + + ); diff --git a/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx b/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx index e235ef715..eb8b3c755 100644 --- a/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx +++ b/client/src/components/sidebar/addGroupDialog/AddGroupDialogActions.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Button, DialogActions } from '@mui/material'; import { styled } from '@mui/system'; -import { FriendType } from './AddGroupDialog'; +import { Group } from './AddGroupDialog'; const StyledDialogActions = styled(DialogActions)` background-color: ${({ theme }) => theme.palette.background.paper}; @@ -11,15 +11,13 @@ const StyledDialogActions = styled(DialogActions)` interface AddGroupDialogActionsProps { handleClose: () => void; handleCreateGroup: () => void; - groupName: string; - selectedFriends: FriendType[]; + group: Group; } const AddGroupDialogActions: React.FC = ({ handleClose, handleCreateGroup, - groupName, - selectedFriends, + group }) => { return ( @@ -27,7 +25,7 @@ const AddGroupDialogActions: React.FC = ({ Cancel