├── Client
├── src
│ ├── App.css
│ ├── vite-env.d.ts
│ ├── index.css
│ ├── store.ts
│ ├── App.tsx
│ ├── main.tsx
│ ├── pages
│ │ ├── home.tsx
│ │ ├── auth.tsx
│ │ ├── joinroom.tsx
│ │ ├── createroom.tsx
│ │ └── room.tsx
│ ├── components
│ │ ├── members.tsx
│ │ ├── result.tsx
│ │ └── chats.tsx
│ └── assets
│ │ └── react.svg
├── .dockerignore
├── postcss.config.js
├── vercel.json
├── .env.example
├── vite.config.ts
├── tailwind.config.js
├── entrypoint.sh
├── tsconfig.node.json
├── .gitignore
├── index.html
├── .eslintrc.cjs
├── tsconfig.json
├── Dockerfile
├── README.md
├── public
│ └── vite.svg
└── package.json
├── Worker
├── .gitignore
├── .dockerignore
├── .env.example
├── entrypoint.sh
├── package.json
├── Dockerfile
├── src
│ └── index.ts
├── tsconfig.json
└── package-lock.json
├── Server
├── .dockerignore
├── .gitignore
├── .env.example
├── entrypoint.sh
├── Dockerfile
├── package.json
├── src
│ ├── index.ts
│ └── utils
│ │ └── roomManager.ts
├── tsconfig.json
└── package-lock.json
├── SystemDesign.png
├── docker-compose.yml
└── readme.md
/Client/src/App.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Worker/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .env
--------------------------------------------------------------------------------
/Client/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env.example
3 | dist
--------------------------------------------------------------------------------
/Server/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env.example
3 | dist
--------------------------------------------------------------------------------
/Worker/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env.example
3 | dist
--------------------------------------------------------------------------------
/Server/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .env
4 | rest.http
--------------------------------------------------------------------------------
/Client/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/SystemDesign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayush-oswal/Collaborative-code-editor/HEAD/SystemDesign.png
--------------------------------------------------------------------------------
/Client/src/index.css:
--------------------------------------------------------------------------------
1 |
2 | /* index.css */
3 | @tailwind base;
4 | @tailwind components;
5 | @tailwind utilities;
6 |
--------------------------------------------------------------------------------
/Client/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/Client/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "rewrites": [
3 | {
4 | "source": "/(.*)",
5 | "destination": "/"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/Client/.env.example:
--------------------------------------------------------------------------------
1 | VITE_REACT_APP_SERVER_URL = ""
2 | # NOTE: only provide the url after http or https eg ://localhost:8080 for local/docker server
3 | VITE_CLERK_PUBLISHABLE_KEY= ""
--------------------------------------------------------------------------------
/Client/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/Worker/.env.example:
--------------------------------------------------------------------------------
1 | X_RAPID_API_KEY = ""
2 | # for local if you run a redis conatiner seperately
3 | # REDIS_URL = "redis://localhost:6379"
4 | # for docker if you use docker-compose up
5 | # REDIS_URL = "redis://redis:6379"
--------------------------------------------------------------------------------
/Client/tailwind.config.js:
--------------------------------------------------------------------------------
1 |
2 | /** @type {import('tailwindcss').Config} */
3 | module.exports = {
4 | content: ["./src/**/*.{html,jsx,tsx}"],
5 | theme: {
6 | extend: {},
7 | },
8 | plugins: [],
9 | }
10 |
--------------------------------------------------------------------------------
/Server/.env.example:
--------------------------------------------------------------------------------
1 |
2 | MONGO_URL = ""
3 | # for local if you run a redis conatiner seperately
4 | # REDIS_URL = "redis://localhost:6379"
5 | # for docker if you use docker-compose up
6 | # REDIS_URL = "redis://redis:6379"
7 | # for prod
8 | # REDIS_URL = "No-Url-provided"
--------------------------------------------------------------------------------
/Client/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Check if node_modules directory does not exist
4 | if [ ! -d "node_modules" ]; then
5 | # Install dependencies if node_modules is missing
6 | npm install
7 | fi
8 |
9 | # Execute the CMD passed as arguments to the script
10 | exec "$@"
11 |
--------------------------------------------------------------------------------
/Server/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Check if node_modules directory does not exist
4 | if [ ! -d "node_modules" ]; then
5 | # Install dependencies if node_modules is missing
6 | npm install
7 | fi
8 |
9 | # Execute the CMD passed as arguments to the script
10 | exec "$@"
11 |
--------------------------------------------------------------------------------
/Worker/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Check if node_modules directory does not exist
4 | if [ ! -d "node_modules" ]; then
5 | # Install dependencies if node_modules is missing
6 | npm install
7 | fi
8 |
9 | # Execute the CMD passed as arguments to the script
10 | exec "$@"
11 |
--------------------------------------------------------------------------------
/Client/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/Client/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | .env
--------------------------------------------------------------------------------
/Client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Collaborative Code Editor - Ayush
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Client/src/store.ts:
--------------------------------------------------------------------------------
1 | // store.ts
2 | import {create} from 'zustand';
3 |
4 | interface UserStore {
5 | username: string;
6 | roomID: string;
7 | setUsername: (username: string) => void;
8 | setRoomID: (roomID:string)=> void;
9 | }
10 |
11 | export const useUserStore = create((set) => ({
12 | username: '',
13 | roomID: '',
14 | setUsername: (username: string) => set({ username }),
15 | setRoomID: (roomID : string) => set({roomID})
16 | }));
17 |
--------------------------------------------------------------------------------
/Client/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:react-hooks/recommended',
8 | ],
9 | ignorePatterns: ['dist', '.eslintrc.cjs'],
10 | parser: '@typescript-eslint/parser',
11 | plugins: ['react-refresh'],
12 | rules: {
13 | 'react-refresh/only-export-components': [
14 | 'warn',
15 | { allowConstantExport: true },
16 | ],
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/Worker/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "worker",
3 | "version": "1.0.0",
4 | "description": "worker node for code execution result",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": " tsc -b && node dist/index.js"
9 | },
10 | "author": "ayush",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@types/node": "^20.12.12",
14 | "axios": "^1.7.2",
15 | "dotenv": "^16.4.5",
16 | "node-fetch": "^3.3.2",
17 | "redis": "^4.6.14"
18 | },
19 | "devDependencies": {
20 | "typescript": "^5.4.5"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Worker/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use an official node image as the base image
2 | FROM node:18
3 |
4 | # Set the working directory
5 | WORKDIR /src
6 |
7 | # Copy package.json and package-lock.json
8 | COPY package*.json ./
9 |
10 | # Install dependencies
11 | RUN npm install
12 |
13 | # Copy the rest of the application code
14 | COPY . .
15 |
16 | # Copy the entrypoint script
17 | COPY entrypoint.sh .
18 |
19 | # Make the entrypoint script executable
20 | RUN chmod +x entrypoint.sh
21 |
22 | # Use the shell to run the entrypoint script
23 | ENTRYPOINT ["sh", "/src/entrypoint.sh"]
24 |
25 | # Command to run the worker
26 | CMD ["npm", "start"]
27 |
--------------------------------------------------------------------------------
/Server/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use an official node image as the base image
2 | FROM node:18
3 |
4 | # Set the working directory
5 | WORKDIR /src
6 |
7 | # Copy package.json and package-lock.json
8 | COPY package*.json ./
9 |
10 | # Install dependencies
11 | RUN npm install
12 |
13 | # Copy the rest of the application code
14 | COPY . .
15 |
16 | # Expose the port the server runs on
17 | EXPOSE 8080
18 |
19 | # Copy the entrypoint script
20 | COPY entrypoint.sh .
21 |
22 | # Make the entrypoint script executable
23 | RUN chmod +x entrypoint.sh
24 |
25 | # Use the shell to run the entrypoint script
26 | ENTRYPOINT ["sh", "/src/entrypoint.sh"]
27 |
28 | # Command to run the server
29 | CMD ["npm", "start"]
30 |
--------------------------------------------------------------------------------
/Client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/Client/src/App.tsx:
--------------------------------------------------------------------------------
1 |
2 | import './App.css'
3 | import { Route, Routes } from 'react-router-dom'
4 | import Room from './pages/room'
5 | import Auth from './pages/auth'
6 | import JoinRoom from './pages/joinroom'
7 | import CreateRoom from './pages/createroom'
8 | import Home from './pages/home'
9 |
10 | function App() {
11 |
12 | return (
13 | <>
14 |
15 | }>
16 | }>
17 | }>
18 | }>
19 | }>
20 |
21 | >
22 | )
23 | }
24 |
25 | export default App
26 |
--------------------------------------------------------------------------------
/Client/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use an official node image as the base image
2 | FROM node:18
3 |
4 | # Set the working directory
5 | WORKDIR /src
6 |
7 | # Copy package.json and package-lock.json
8 | COPY package*.json ./
9 |
10 | # Install dependencies
11 | RUN npm install
12 |
13 | RUN npm install @rollup/rollup-linux-x64-gnu
14 |
15 | # Copy the rest of the application code
16 | COPY . .
17 |
18 | # Expose the port the app runs on
19 | EXPOSE 5173
20 |
21 | # Copy the entrypoint script
22 | COPY entrypoint.sh .
23 |
24 | # Make the entrypoint script executable
25 | RUN chmod +x entrypoint.sh
26 |
27 | # Use the shell to run the entrypoint script
28 | ENTRYPOINT ["sh", "/src/entrypoint.sh"]
29 |
30 | # Command to run the app in development mode
31 | CMD ["npm", "run", "dev"]
32 |
--------------------------------------------------------------------------------
/Client/src/main.tsx:
--------------------------------------------------------------------------------
1 |
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.tsx'
4 | import './index.css'
5 | import { BrowserRouter } from 'react-router-dom'
6 | import { ChakraProvider } from '@chakra-ui/react';
7 | import { ClerkProvider } from '@clerk/clerk-react'
8 |
9 | // Import your publishable key
10 | const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
11 |
12 | if (!PUBLISHABLE_KEY) {
13 | throw new Error("Missing Publishable Key")
14 | }
15 |
16 | ReactDOM.createRoot(document.getElementById('root')!).render(
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | )
25 |
--------------------------------------------------------------------------------
/Server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "description": "Web Socket Server",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": " tsc -b && node dist/index.js"
9 | },
10 | "author": "Babu",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@types/bcrypt": "^5.0.2",
14 | "@types/express": "^4.17.21",
15 | "@types/ws": "^8.5.10",
16 | "bcrypt": "^5.1.1",
17 | "dotenv": "^16.4.5",
18 | "express": "^4.19.2",
19 | "mongoose": "^8.4.0",
20 | "redis": "^4.6.14",
21 | "ws": "^8.17.0"
22 | },
23 | "devDependencies": {
24 | "@types/bcrypt": "^5.0.2",
25 | "@types/cors": "^2.8.17",
26 | "cors": "^2.8.5",
27 | "typescript": "^5.4.5"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.8'
2 |
3 | services:
4 | redis:
5 | image: "redis:latest"
6 | container_name: redis
7 | ports:
8 | - "6379:6379"
9 | volumes:
10 | - redis-data:/data
11 |
12 | server:
13 | build:
14 | context: ./Server
15 | dockerfile: Dockerfile
16 | container_name: server
17 | depends_on:
18 | - redis
19 | ports:
20 | - "8080:8080"
21 |
22 | worker:
23 | build:
24 | context: ./Worker
25 | dockerfile: Dockerfile
26 | container_name: worker
27 | depends_on:
28 | - redis
29 |
30 | client:
31 | build:
32 | context: ./Client
33 | dockerfile: Dockerfile
34 | container_name: client
35 | depends_on:
36 | - server
37 | ports:
38 | - "5173:5173"
39 |
40 | volumes:
41 | redis-data:
42 |
--------------------------------------------------------------------------------
/Client/src/pages/home.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useNavigate } from 'react-router-dom';
3 |
4 |
5 | const Home: React.FC = () => {
6 | const Navigate = useNavigate()
7 |
8 | return (
9 |
10 |
Welcome to CodeCollab
11 |
12 | CodeCollab is a collaborative code editor where you can create or join rooms, chat, write code together, and even run it in real-time.
13 |
14 |
20 |
21 | );
22 | };
23 |
24 | export default Home;
25 |
--------------------------------------------------------------------------------
/Client/src/pages/auth.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react';
2 | import { SignInButton, SignedOut, useUser } from '@clerk/clerk-react';
3 | import { useUserStore } from '../store';
4 | import { useNavigate } from 'react-router-dom';
5 |
6 | const Auth: React.FC = () => {
7 | const { user } = useUser();
8 | const { setUsername } = useUserStore()
9 | const Navigate = useNavigate();
10 |
11 | useEffect(() => {
12 | if (user) {
13 | const clerkUsername = user.username || user.firstName || user.emailAddresses[0].emailAddress;
14 | setUsername(clerkUsername);
15 | Navigate("/join")
16 | }
17 | }, [user, setUsername]);
18 |
19 | return (
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 | };
31 |
32 | export default Auth;
33 |
--------------------------------------------------------------------------------
/Client/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default {
18 | // other rules...
19 | parserOptions: {
20 | ecmaVersion: 'latest',
21 | sourceType: 'module',
22 | project: ['./tsconfig.json', './tsconfig.node.json'],
23 | tsconfigRootDir: __dirname,
24 | },
25 | }
26 | ```
27 |
28 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
31 |
--------------------------------------------------------------------------------
/Client/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Client/src/components/members.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Box, Button } from '@chakra-ui/react';
3 | import toast from 'react-hot-toast';
4 |
5 | interface MembersProps {
6 | users: string[];
7 | roomId: string;
8 | onLeave: () => void;
9 | }
10 |
11 | const Members: React.FC = ({ users, roomId, onLeave }) => {
12 | const copyRoomIdToClipboard = () => {
13 | navigator.clipboard.writeText(roomId);
14 | toast.success('Room ID copied to clipboard!');
15 | };
16 |
17 | return (
18 |
19 |
35 | {users.map((user, index) => (
36 | {user}
37 | ))}
38 |
39 |
40 |
41 |
42 |
43 |
44 | );
45 | };
46 |
47 | export default Members;
48 |
--------------------------------------------------------------------------------
/Client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite --host",
8 | "build": "tsc && vite build",
9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@chakra-ui/icons": "^2.1.1",
14 | "@chakra-ui/react": "^2.8.2",
15 | "@clerk/clerk-react": "^5.9.0",
16 | "@codemirror/lang-cpp": "^6.0.2",
17 | "@codemirror/lang-java": "^6.0.1",
18 | "@codemirror/lang-javascript": "^6.2.2",
19 | "@codemirror/lang-python": "^6.1.6",
20 | "@emotion/react": "^11.11.4",
21 | "@emotion/styled": "^11.11.5",
22 | "@types/node": "^20.12.11",
23 | "@uiw/react-codemirror": "^4.22.1",
24 | "framer-motion": "^11.2.0",
25 | "react": "^18.2.0",
26 | "react-dom": "^18.2.0",
27 | "react-hot-toast": "^2.4.1",
28 | "react-router-dom": "^6.23.1",
29 | "uuidv4": "^6.2.13",
30 | "zustand": "^4.5.2"
31 | },
32 | "devDependencies": {
33 | "@types/react": "^18.2.66",
34 | "@types/react-dom": "^18.2.22",
35 | "@typescript-eslint/eslint-plugin": "^7.2.0",
36 | "@typescript-eslint/parser": "^7.2.0",
37 | "@vitejs/plugin-react": "^4.2.1",
38 | "autoprefixer": "^10.4.19",
39 | "dotenv": "^16.4.5",
40 | "eslint": "^8.57.0",
41 | "eslint-plugin-react-hooks": "^4.6.0",
42 | "eslint-plugin-react-refresh": "^0.4.6",
43 | "postcss": "^8.4.38",
44 | "tailwindcss": "^3.4.3",
45 | "typescript": "^5.2.2",
46 | "vite": "^5.2.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Client/src/components/result.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Modal,
4 | ModalOverlay,
5 | ModalContent,
6 | ModalHeader,
7 | ModalFooter,
8 | ModalBody,
9 | ModalCloseButton,
10 | Button,
11 | Text,
12 | useColorModeValue
13 | } from '@chakra-ui/react';
14 |
15 | interface ResultMessage {
16 | Title: string;
17 | stdout: string;
18 | stderr: string | null;
19 | status: string;
20 | compile_output: string | null;
21 | }
22 |
23 | interface ResultModalProps {
24 | isOpen: boolean;
25 | onClose: () => void;
26 | resultMessage: ResultMessage;
27 | }
28 |
29 | const ResultModal: React.FC = ({ isOpen, onClose, resultMessage }) => {
30 | const bgColor = useColorModeValue('gray.800', 'gray.800');
31 | const textColor = useColorModeValue('white', 'white');
32 |
33 | return (
34 |
35 |
36 |
37 | {resultMessage.Title}
38 |
39 |
40 | Status: {resultMessage.status}
41 | Output: {resultMessage.stdout}
42 | { resultMessage.compile_output && Compile Output: {resultMessage.compile_output}}
43 | {resultMessage.stderr && Error: {resultMessage.stderr}}
44 |
45 |
46 |
49 |
50 |
51 |
52 | );
53 | };
54 |
55 | export default ResultModal;
56 |
--------------------------------------------------------------------------------
/Client/src/components/chats.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Box, Flex, Input, IconButton } from "@chakra-ui/react";
3 | import { ArrowForwardIcon } from "@chakra-ui/icons";
4 |
5 | type chat = {
6 | username: string;
7 | message: string;
8 | };
9 |
10 | interface chatProps {
11 | chats: chat[];
12 | addChat: (msg: string) => void;
13 | }
14 |
15 | const Chats: React.FC = ({ chats, addChat }) => {
16 | const [msg, setMsg] = useState("");
17 |
18 | const handleSendMessage = () => {
19 | if (msg.trim()) {
20 | addChat(msg);
21 | setMsg("");
22 | }
23 | };
24 |
25 | return (
26 |
27 |
34 | {chats.map((chat, index) => (
35 |
36 | {chat.username}
37 | {chat.message}
38 |
39 | ))}
40 |
41 |
42 | setMsg(e.target.value)}
45 | placeholder="Type a message..."
46 | bg="gray.700"
47 | color="blue.200"
48 | border="none"
49 | _placeholder={{ color: "blue.400" }}
50 | flex="1"
51 | />
52 | }
55 | onClick={handleSendMessage}
56 | ml="2"
57 | bg="blue.500"
58 | _hover={{ bg: "blue.600" }}
59 | />
60 |
61 |
62 | );
63 | };
64 |
65 | export default Chats;
66 |
--------------------------------------------------------------------------------
/Client/src/pages/joinroom.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import { useNavigate } from 'react-router-dom';
3 | import {useUserStore} from '../store'
4 | import { UserButton, useUser } from '@clerk/clerk-react';
5 |
6 | const JoinRoom: React.FC = () => {
7 | const Navigate = useNavigate()
8 | const { roomID } = useUserStore();
9 | const [roomId,setRoomId] = useState("")
10 | const {user} = useUser()
11 | useEffect(()=>{
12 | if(!user?.username){
13 | Navigate("/auth")
14 | }
15 | if(roomID!="") setRoomId(roomID)
16 | })
17 | const handleSubmit = (event: React.FormEvent) => {
18 | event.preventDefault();
19 | Navigate(`/room/${roomId}`)
20 | };
21 |
22 | return (
23 |
24 |
25 |
26 |
Hello, {user?.username}
27 |
28 |
29 |
30 |
Join Room
31 |
46 |
47 | Don't have a room?{' '}
48 |
51 |
52 |
53 | );
54 | };
55 |
56 | export default JoinRoom;
57 |
--------------------------------------------------------------------------------
/Server/src/index.ts:
--------------------------------------------------------------------------------
1 | import express from 'express'
2 | import { createServer } from 'http';
3 | import { Request, Response } from 'express'
4 | import { WebSocketServer } from 'ws'
5 | import { createClient } from 'redis'
6 | import cors from 'cors'
7 | import { RoomManager } from './utils/roomManager'
8 | import dotenv from "dotenv";
9 |
10 | dotenv.config();
11 |
12 | const app = express()
13 | const httpServer = createServer(app);
14 |
15 | app.use(cors())
16 | app.use(express.json());
17 |
18 | httpServer.listen(8080, () => {
19 | console.log(`Server listening on port 8080`);
20 | });
21 |
22 | app.get("/",(req:Request,res:Response)=>{
23 | res.status(200).json({message:"Hello world"})
24 | })
25 |
26 | //connect to redis after launching it from docker
27 |
28 | const redis_url = process.env.REDIS_URL === "No-Url-provided" ? "" : process.env.REDIS_URL
29 |
30 | const redisClient = createClient({
31 | url: redis_url
32 | });
33 |
34 | const redisClientSubscribing = createClient({
35 | url: redis_url
36 | });
37 |
38 |
39 | redisClient.connect().catch(err=>{console.log(err)})
40 | redisClientSubscribing.connect().catch(err=>{console.log(err)})
41 |
42 |
43 | const wss = new WebSocketServer({ server: httpServer });
44 |
45 | wss.on('connection', function connection(ws) {
46 | ws.on('error', console.error);
47 |
48 | ws.on('message', function message(data, isBinary) {
49 | const message = JSON.parse(data.toString());
50 | if(message.Title==="User-joined"){
51 | RoomManager.getInstance().handleUserJoined(message, ws);
52 | }
53 | else if(message.Title==="User-left"){
54 | RoomManager.getInstance().handleUserLeft(message)
55 | }
56 | else if(message.Title==="New-chat"){
57 | RoomManager.getInstance().handleNewChat(message)
58 | }
59 | else if(message.Title==="lang-change"){
60 | RoomManager.getInstance().handleLangChange(message)
61 | }
62 | else if(message.Title==="Code-change"){
63 | RoomManager.getInstance().handleCodeChange(message)
64 | }
65 | else if(message.Title==="Submitted"){
66 | RoomManager.getInstance().handleSubmitted(message,ws)
67 | }
68 | });
69 |
70 | ws.send(JSON.stringify({Title : "Greet" , msg:'Hello! Message From Server!!'}));
71 | });
72 |
73 | app.post("/create",(req:Request,res:Response)=>{
74 |
75 | const {username, roomName, roomId} = req.body;
76 | if(!username || !roomName || !roomId){
77 | res.status(400).json({error : "Some error"})
78 | return;
79 | }
80 |
81 | try{
82 | RoomManager.getInstance().create(req.body)
83 | res.status(200).json({ message: 'Room created successfully' });
84 | }
85 | catch(e){
86 | res.status(500).json({ message: 'Server error' });
87 | }
88 |
89 | })
--------------------------------------------------------------------------------
/Client/src/pages/createroom.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { v4 as uuidv4 } from 'uuid';
3 | import { useNavigate } from 'react-router-dom';
4 | import { useUserStore } from '../store';
5 | import { useUser } from '@clerk/clerk-react';
6 | import { Spinner } from '@chakra-ui/react';
7 |
8 | const CreateRoom: React.FC = () => {
9 | const [roomName, setRoomName] = useState('');
10 | const [roomId, setRoomId] = useState('');
11 | const [loading, setLoading] = useState(false); // New state for spinner
12 | const Navigate = useNavigate();
13 | const { setRoomID } = useUserStore();
14 | const { user } = useUser();
15 | const username = user?.username;
16 |
17 | useEffect(() => {
18 | if (username == '') {
19 | Navigate('/auth');
20 | }
21 | });
22 |
23 | const handleGenerateRoomId = () => {
24 | const newRoomId = uuidv4();
25 | setRoomId(newRoomId);
26 | };
27 |
28 | const handleSubmit = async (event: React.FormEvent) => {
29 | event.preventDefault();
30 | if (!roomId || !roomName) {
31 | alert('Fill name and id');
32 | return;
33 | }
34 | setLoading(true);
35 | const serverUrl = import.meta.env.VITE_REACT_APP_SERVER_URL;
36 | let url = '';
37 | if (serverUrl === '://localhost:8080') {
38 | url = `http${serverUrl}`;
39 | } else {
40 | url = `https${serverUrl}`;
41 | }
42 | try {
43 | const response = await fetch(`${url}/create`, {
44 | method: 'POST',
45 | headers: {
46 | 'Content-Type': 'application/json',
47 | },
48 | body: JSON.stringify({
49 | username,
50 | roomName,
51 | roomId,
52 | }),
53 | });
54 | setLoading(false);
55 | if (response.ok) {
56 | // Add a toast here
57 | setRoomID(roomId);
58 | Navigate('/join');
59 | } else {
60 | alert('Error creating room');
61 | }
62 | } catch (err) {
63 | console.log(err);
64 | }
65 | };
66 |
67 | return (
68 |
69 |
Create Room
70 |
107 |
108 | );
109 | };
110 |
111 | export default CreateRoom;
112 |
--------------------------------------------------------------------------------
/Client/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Worker/src/index.ts:
--------------------------------------------------------------------------------
1 | import { createClient } from "redis";
2 | import axios from "axios";
3 | import dotenv from "dotenv";
4 |
5 |
6 | dotenv.config();
7 |
8 | const redisClient = createClient({
9 | url: process.env.REDIS_URL
10 | });
11 |
12 |
13 | async function processSubmission(submission: string) {
14 | const { roomId, code, language } = JSON.parse(submission);
15 | console.log(roomId, code, language);
16 |
17 | const judge0Url = 'https://judge0.p.rapidapi.com/submissions?fields=*&base64_encoded=false&wait=true'
18 | const judge0Key = process.env.X_RAPID_API_KEY || ""
19 |
20 | const payload = {
21 | source_code: code,
22 | language_id: getLanguageId(language),
23 | };
24 |
25 | try {
26 | const response = await axios.post(judge0Url, payload, {
27 | headers: {
28 | 'Content-Type': 'application/json',
29 | 'x-rapidapi-host': 'judge0-ce.p.rapidapi.com',
30 | 'x-rapidapi-key': judge0Key,
31 | },
32 | });
33 |
34 | if (!response.data || !response.data.status || response.data.status.id <= 2) {
35 | throw new Error(`Judge0 API responded with status ${response.data.status}`);
36 | }
37 |
38 | let result = response.data;
39 |
40 | if (result.status.id <= 2) {
41 | //means still processing
42 | result = await pollJudge0Result(result.token, judge0Key);
43 | }
44 |
45 | await redisClient.publish(roomId, JSON.stringify(result));
46 | console.log(`Published result to room: ${roomId}`);
47 | } catch (error) {
48 | console.error(`Error processing submission for room: ${roomId}`, error);
49 | await redisClient.publish(roomId,"error");
50 | }
51 | }
52 |
53 | async function pollJudge0Result(token: string, apiKey: string) {
54 | const judge0ResultUrl = `https://judge0.p.rapidapi.com/submissions/${token}?base64_encoded=false`;
55 |
56 | while (true) {
57 | try {
58 | const response = await axios.get(judge0ResultUrl, {
59 | headers: {
60 | 'Content-Type': 'application/json',
61 | 'x-rapidapi-host': 'judge0-ce.p.rapidapi.com',
62 | 'x-rapidapi-key': apiKey,
63 | },
64 | });
65 |
66 | if (!response.data || !response.data.status) {
67 | throw new Error(`Invalid response from Judge0 API`);
68 | }
69 |
70 | const resultData = response.data;
71 |
72 | if (resultData.status.id > 2) {
73 | //i.e result is processed
74 | return resultData;
75 | } else {
76 | await new Promise(resolve => setTimeout(resolve, 2000));
77 | }
78 | } catch (error) {
79 | console.error(`Error polling Judge0 API for token ${token}`, error);
80 | await new Promise(resolve => setTimeout(resolve, 2000));
81 | }
82 | }
83 | }
84 |
85 | async function startWorker() {
86 | try {
87 | await redisClient.connect();
88 | console.log("Worker connected to Redis.");
89 |
90 | while (true) {
91 | try {
92 | const data = await redisClient.brPop("submissions", 0);
93 | if (data) {
94 | await processSubmission(data.element);
95 | }
96 | } catch (err) {
97 | console.error("Error processing submission:", err);
98 | }
99 | }
100 | } catch (err) {
101 | console.log(err);
102 | }
103 | }
104 |
105 | function getLanguageId(language: string): number {
106 | const languageMap: { [key: string]: number } = {
107 | "javascript": 63,
108 | "python": 71,
109 | "cpp": 54,
110 | "java": 62
111 | };
112 | return languageMap[language.toLowerCase()];
113 | }
114 |
115 | startWorker().catch(console.error);
116 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
2 | # System Design
3 |
4 | 
5 |
6 | # 🎉 Collaborative Code Editor
7 |
8 | Welcome to the Collaborative Code Editor (CCE) repository! This application allows multiple users to collaboratively write and edit code in real-time, leveraging the power of WebSockets. Users can sign up or log in with a unique username, create or join rooms with unique room IDs, and interact with other users through real-time chat and code editing. Each room supports multiple users who can collaboratively write code, select the programming language, submit their code for execution, and view the results together. The backend handles code execution using the Judge0 API and Redis for task queuing and pub/sub functionality. This makes CCE an ideal platform for collaborative coding sessions, educational environments, and coding competitions.
9 |
10 | ## 🌟 Features
11 | - **🔒 User Authentication**: Sign up and log in with unique usernames.
12 | - **🛏️ Room Management**: Create or join rooms with unique IDs.
13 | - **📝 Real-time Collaboration**: Code and chat in real-time with other users in the room.
14 | - **🌐 Multi-language support**: Choose the programming language for your code, supports 4 languages (python,javascript,java,c++)
15 | - **🚀 Code Submission and Execution**: Submit code and view results using the Judge0 API.
16 | - **🔄 Real-time Updates**: Automatic updates for code changes, language selection, user activity, and chat messages.
17 |
18 | ## 🛠️ Tech Stack
19 | - **Frontend**: Vite, React, TypeScript
20 | - **Backend**: Express, HTTP for WebSockets, MongoDB
21 | - **Queue and Pub/Sub System**: Redis
22 |
23 | ## 📦 Setup Guide
24 |
25 | ### Manual Setup
26 | 1. **Clone the repository**:
27 | ```sh
28 | git clone https://github.com/yourusername/collaborative-code-editor.git
29 | cd collaborative-code-editor
30 | ```
31 |
32 | 2. **Install dependencies for each service**:
33 | ```sh
34 | # Server
35 | cd server
36 | npm install
37 |
38 | # Worker
39 | cd ../worker
40 | npm install
41 |
42 | # Client
43 | cd ../client
44 | npm install
45 | ```
46 |
47 | 3. **Create a `.env` file** in each folder and configure your environment variables: (Refer the .env.example file)
48 | ```env
49 | # Example Client .env file
50 | VITE_REACT_APP_SERVER_URL =
51 | # Example Server .env file
52 | MONGO_URL =
53 | REDIS_URL =
54 | # Example Worker .env file
55 | //judge0 api key
56 | X_RAPID_API_KEY =
57 | REDIS_URL =
58 |
59 |
60 | 4. **Start redis locally**
61 | ```sh
62 | # In separate terminal
63 | # Using Docker
64 | docker run -p 6379:6379 --name redis-server -d redis
65 | ```
66 |
67 | 5. **Start each service**:
68 | ```sh
69 | # Start Server
70 | cd server
71 | npm run start
72 |
73 | # Start Worker
74 | cd ../worker
75 | npm run start
76 |
77 | # Start Client
78 | cd ../client
79 | npm run dev
80 | ```
81 |
82 | ### Docker Setup
83 | 1. **Navigate to the root directory**:
84 | ```sh
85 | cd path/to/collaborative-code-editor
86 | ```
87 |
88 | 2. **Create a `.env` file** in each folder and configure your environment variables: (Refer the .env.example file)
89 | ```env
90 | # Example Client .env file
91 | VITE_REACT_APP_SERVER_URL =
92 | # Example Server .env file
93 | MONGO_URL =
94 | REDIS_URL =
95 | # Example Worker .env file
96 | //judge0 api key
97 | X_RAPID_API_KEY =
98 | REDIS_URL =
99 |
100 | 3. **Build and run the stack of containers**:
101 | ```sh
102 | docker-compose up --build
103 | ```
104 |
105 | ### Troubleshooting
106 | - If you encounter an issue with `bcrypt` related to an invalid ELF header, perform the following steps:
107 | ```sh
108 | # Enter the server container using bin/bash
109 | docker exec -it server_container_name /bin/bash
110 |
111 | # Inside the container, reinstall bcrypt
112 | npm install bcrypt
113 | ```
114 |
115 |
116 | ## 🚀 How It Works
117 | 1. **Sign Up / Log In**: Users sign up or log in with a unique username.
118 | 2. **Create / Join Room**: Users can create a new room with a unique room ID or join an existing room.
119 | 3. **WebSocket Connection**: Upon joining a room, a WebSocket connection is established.
120 | 4. **User Mapping**: On the server, the username is mapped to the WebSocket connection and added to the room's users array.
121 | 5. **Code Editor**: Users can write and edit code in a collaborative editor with a language selection option.
122 | 6. **Submit Code**: When a user submits code, it is pushed to a Redis queue.
123 | 7. **Worker Processing**: A worker listens to the queue, processes the code using the Judge0 API, and publishes the result to Redis.
124 | 8. **Result Broadcasting**: The main server subscribes to the result channel and broadcasts the result to all clients in the room.
125 |
126 | ## 🎨 Room Structure
127 | - **Name**: The name of the room.
128 | - **Room ID**: A unique identifier for the room.
129 | - **Users**: An array of user objects `{username, wss}`.
130 | - **Code**: The current code in the editor.
131 | - **Chats**: An array of chat objects `{username, message}`.
132 | - **Language**: The selected programming language.
133 | - **Result**: The result of the last code execution.
134 |
135 | ## 📬 Contributing
136 | We welcome contributions to the Collaborative Code Editor! To contribute:
137 | 1. Fork the repository.
138 | 2. Create a new branch (`git checkout -b feature/your-feature-name`).
139 | 3. Make your changes.
140 | 4. Commit your changes (`git commit -m 'Add some feature'`).
141 | 5. Push to the branch (`git push origin feature/your-feature-name`).
142 | 6. Open a Pull Request.
143 |
144 | Please ensure your code follows our coding standards and includes tests where applicable.
145 |
146 | ## 📄 License
147 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
148 |
--------------------------------------------------------------------------------
/Server/src/utils/roomManager.ts:
--------------------------------------------------------------------------------
1 | import { WebSocket } from 'ws'
2 |
3 | interface room {
4 | name: string,
5 | roomId: string,
6 | users: Array<{
7 | username: string,
8 | ws: WebSocket
9 | }>,
10 | code: string,
11 | chats: Array<{
12 | username: string,
13 | message: string
14 | }>,
15 | language: string,
16 | result: string
17 | }
18 |
19 | import { createClient } from 'redis'
20 |
21 | export class RoomManager {
22 | private static instance : RoomManager;
23 | private rooms : room[] = [];
24 |
25 | private constructor(){
26 |
27 | }
28 |
29 | public static getInstance(): RoomManager {
30 | if (!RoomManager.instance) {
31 | RoomManager.instance = new RoomManager();
32 | }
33 | return RoomManager.instance;
34 | }
35 |
36 | public create(roomData : any){
37 |
38 | const { roomName, roomId} = roomData
39 |
40 | const newRoom: room = {
41 | name: roomName,
42 | roomId: roomId,
43 | users: [],
44 | code: "",
45 | chats: [],
46 | language: "python",
47 | result: ""
48 | };
49 |
50 | this.rooms.push(newRoom)
51 |
52 | }
53 |
54 | public handleUserJoined(message:any, ws : WebSocket) {
55 | const { roomId, username } = message;
56 | if(username==="") return;
57 | // Find the room based on roomId
58 | const room = this.rooms.find(room => room.roomId === roomId);
59 | if (!room) {
60 | const notFoundMessage = JSON.stringify({
61 | Title : "Not-found"
62 | })
63 | ws.send(notFoundMessage)
64 | return;
65 | }
66 |
67 |
68 | // Check if the user is already in the room
69 | const existingUserIndex = room.users.findIndex(user => user.username === username);
70 | if (existingUserIndex !== -1) {
71 | // Update the existing user's WebSocket connection
72 | room.users[existingUserIndex].ws = ws;
73 |
74 | // Send room info to the existing user
75 | const roomInfoMessage = JSON.stringify({
76 | Title: "Room-Info",
77 | roomId,
78 | roomName: room.name,
79 | users: room.users.map(user => user.username),
80 | code: room.code,
81 | chats: room.chats,
82 | language: room.language,
83 | result: room.result
84 | });
85 | ws.send(roomInfoMessage);
86 | return;
87 | }
88 |
89 | // Add the user to the room
90 | room.users.push({ username, ws });
91 |
92 | // Send a message to all other users in the room about the new user
93 | const newUserMessage = JSON.stringify({
94 | Title: "New-User",
95 | username
96 | });
97 |
98 | room.users.forEach(user => {
99 | if (user.ws !== ws && user.ws.readyState === WebSocket.OPEN) {
100 | user.ws.send(newUserMessage);
101 | }
102 | });
103 |
104 | // Send room info to the newly joined user
105 | const roomInfoMessage = JSON.stringify({
106 | Title: "Room-Info",
107 | roomId,
108 | roomName: room.name,
109 | users: room.users.map(user => user.username),
110 | code: room.code,
111 | chats: room.chats,
112 | language: room.language,
113 | result: room.result
114 | });
115 | ws.send(roomInfoMessage);
116 | }
117 |
118 | public handleUserLeft(message: any) {
119 | const { roomId, username } = message;
120 | if(username==="") return;
121 | // Find the room based on roomId
122 | const room = this.rooms.find(room => room.roomId === roomId);
123 | if (!room) {
124 | return;
125 | }
126 |
127 | // Remove the user from the room
128 | room.users = room.users.filter(user => user.username !== username);
129 |
130 | if(room.users.length===0){
131 | this.rooms = this.rooms.filter(room => room.roomId !== roomId)
132 | return;
133 | }
134 |
135 | // Notify remaining users in the room
136 | const userLeftMessage = JSON.stringify({
137 | Title: "User-left",
138 | username,
139 | users: room.users.map(user => user.username)
140 | });
141 |
142 | room.users.forEach(user => {
143 | if (user.ws.readyState === WebSocket.OPEN) {
144 | user.ws.send(userLeftMessage);
145 | }
146 | });
147 | }
148 |
149 | public handleNewChat(message:any){
150 | const {roomId, username, chat} = message
151 | const room = this.rooms.find(room => room.roomId === roomId);
152 | if (!room) {
153 | return;
154 | }
155 | room.chats.push({username,message:chat})
156 | const newChatMessage = JSON.stringify({
157 | Title: "New-chat",
158 | username,
159 | chat
160 | })
161 | room.users.forEach(user => {
162 | if (user.ws.readyState === WebSocket.OPEN) {
163 | user.ws.send(newChatMessage);
164 | }
165 | });
166 | }
167 |
168 | public handleLangChange(message:any){
169 | const { roomId, lang } = message
170 | const room = this.rooms.find(room => room.roomId === roomId);
171 | if (!room) {
172 | return;
173 | }
174 | room.language = lang;
175 | const langChangeMessage = {
176 | Title:"lang-change",
177 | lang
178 | }
179 | room.users.forEach(user => {
180 | if (user.ws.readyState === WebSocket.OPEN) {
181 | user.ws.send(JSON.stringify(langChangeMessage));
182 | }
183 | });
184 | }
185 |
186 | public handleCodeChange(message:any){
187 | const { roomId, code } = message
188 | const room = this.rooms.find(room => room.roomId === roomId);
189 | if (!room) {
190 | return;
191 | }
192 | room.code=code
193 | const CodeChangeMessage = {
194 | Title:"Code-change",
195 | code
196 | }
197 | room.users.forEach(user => {
198 | if (user.ws.readyState === WebSocket.OPEN) {
199 | user.ws.send(JSON.stringify(CodeChangeMessage));
200 | }
201 | });
202 | }
203 |
204 | public async handleSubmitted(message:any , ws : WebSocket) {
205 |
206 | if(process.env.REDIS_URL === "No-Url-provided" || !process.env.REDIS_URL){
207 | const resultMessage = {
208 | Title: "No-worker"
209 | }
210 | ws.send(JSON.stringify(resultMessage))
211 | return;
212 | }
213 |
214 | const redisClient = createClient({
215 | url: process.env.REDIS_URL
216 | });
217 |
218 | const redisClientSubscribing = createClient({
219 | url: process.env.REDIS_URL
220 | });
221 |
222 |
223 | redisClient.connect().catch(err=>{console.log(err)})
224 | redisClientSubscribing.connect().catch(err=>{console.log(err)})
225 |
226 | const {roomId} = message
227 | const room = this.rooms.find(room => room.roomId === roomId);
228 | if (!room) {
229 | return;
230 | }
231 |
232 | const SubmitClickedMessage = {
233 | Title:"Submit-clicked"
234 | }
235 |
236 | room.users.forEach(user => {
237 | if (user.ws.readyState === WebSocket.OPEN) {
238 | user.ws.send(JSON.stringify(SubmitClickedMessage));
239 | }
240 | });
241 |
242 |
243 |
244 | //push the message into submissions queue
245 | await redisClient.lPush("submissions",JSON.stringify(message))
246 |
247 |
248 | //subscribe to the roomId
249 | redisClientSubscribing.subscribe(roomId, (result) => {
250 | redisClientSubscribing.unsubscribe(roomId)
251 | // Parse the result received from the subscription
252 | if(result==="error"){
253 | const msg = {
254 | Title : "error"
255 | }
256 | room.users.forEach(user => {
257 | if (user.ws.readyState === WebSocket.OPEN) {
258 | user.ws.send(JSON.stringify(msg));
259 | }
260 | });
261 | }
262 | else{
263 | const parsedResult = JSON.parse(result);
264 | // Create a new JSON object containing the required fields
265 | const resultMessage = {
266 | Title: "Result",
267 | stdout: parsedResult.stdout,
268 | stderr: parsedResult.stderr,
269 | status: parsedResult.status.description,
270 | compile_output: parsedResult.compile_output
271 | };
272 |
273 | // Send the resultMessageString to each user in the room
274 | room.users.forEach(user => {
275 | if (user.ws.readyState === WebSocket.OPEN) {
276 | user.ws.send(JSON.stringify(resultMessage));
277 | }
278 | });
279 | }
280 | });
281 | }
282 |
283 | }
--------------------------------------------------------------------------------
/Server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | "rootDir": "./src", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | "outDir": "./dist", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68 | // "newLine": "crlf", /* Set the newline character for emitting files. */
69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75 |
76 | /* Interop Constraints */
77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83 |
84 | /* Type Checking */
85 | "strict": true, /* Enable all strict type-checking options. */
86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104 |
105 | /* Completeness */
106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/Worker/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | "rootDir": "./src", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | "outDir": "./dist", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68 | // "newLine": "crlf", /* Set the newline character for emitting files. */
69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75 |
76 | /* Interop Constraints */
77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83 |
84 | /* Type Checking */
85 | "strict": true, /* Enable all strict type-checking options. */
86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104 |
105 | /* Completeness */
106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/Client/src/pages/room.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react'
2 | import { useParams, useNavigate } from 'react-router-dom'
3 | import {useUserStore} from '../store'
4 | import { Box, Button, Flex, IconButton, Select, useDisclosure, Drawer, DrawerBody, DrawerHeader, DrawerOverlay, DrawerContent, DrawerCloseButton, useBreakpointValue, Spinner } from '@chakra-ui/react';
5 | import { HamburgerIcon, ChatIcon } from '@chakra-ui/icons';
6 | import CodeMirror from '@uiw/react-codemirror';
7 | import { javascript } from '@codemirror/lang-javascript';
8 | import { cpp } from '@codemirror/lang-cpp';
9 | import { java } from '@codemirror/lang-java';
10 | import { python } from '@codemirror/lang-python';
11 | import Members from '../components/members';
12 | import Chats from '../components/chats';
13 | import ResultModal from '../components/result';
14 | import toast, { Toaster } from 'react-hot-toast';
15 | import { useUser } from '@clerk/clerk-react';
16 |
17 |
18 | type chat =
19 | {
20 | username:string,
21 | message:string
22 | }
23 |
24 | const Room: React.FC = () => {
25 | const {roomId} = useParams();
26 | const Navigate = useNavigate()
27 | const { setRoomID } = useUserStore();
28 | const {user} = useUser();
29 | const username = user?.username
30 | const [roomName,setRoomName] = useState("")
31 | const [users, setUsers] = useState([])
32 | const [chats,setChats] = useState([])
33 | const [result,setResult] = useState(null)
34 | const [language,setLanguage] = useState("")
35 | const [code,setCode] = useState("")
36 | const [socket, setSocket] = useState(null);
37 | const [submitClicked, setSubmitClicked] = useState(false);
38 | const [isModalOpen, setIsModalOpen] = useState(false);
39 |
40 | //fire socket events on lang change, chat , code change, new user is done, add button leave user and copy room id
41 |
42 | useEffect(()=>{
43 | if(username==''){
44 | Navigate("/auth")
45 | }
46 | let ws_url = ""
47 | if(import.meta.env.VITE_REACT_APP_SERVER_URL === "://localhost:8080"){
48 | ws_url = `ws${import.meta.env.VITE_REACT_APP_SERVER_URL}`
49 | }
50 | else{
51 | ws_url = `wss${import.meta.env.VITE_REACT_APP_SERVER_URL}`
52 | }
53 | const newSocket = new WebSocket(ws_url);
54 | newSocket.onopen = () => {
55 | console.log('Connection established');
56 | const msg = {
57 | Title : "User-joined",
58 | roomId,
59 | username
60 | }
61 | newSocket.send(JSON.stringify(msg))
62 | }
63 | newSocket.onmessage = (message) => {
64 | const parsedMessage = JSON.parse(message.data);
65 | if (parsedMessage.Title === "Room-Info") {
66 | setUsers(parsedMessage.users);
67 | setCode(parsedMessage.code);
68 | setLanguage(parsedMessage.language);
69 | setResult(parsedMessage.result);
70 | setChats(parsedMessage.chats);
71 | setRoomName(parsedMessage.roomName)
72 | }
73 | else if(parsedMessage.Title === "Not-found"){
74 | alert("No room found")
75 | Navigate("/join")
76 | }
77 | else if (parsedMessage.Title === "New-User") {
78 | toast.success(`${parsedMessage.username} joined` )
79 | setUsers(prevUsers => [...prevUsers, parsedMessage.username]);
80 | }
81 | else if(parsedMessage.Title === "User-left"){
82 | toast.error(`${parsedMessage.username} left`)
83 | setUsers(parsedMessage.users)
84 | }
85 | else if(parsedMessage.Title === "New-chat"){
86 | const {username, chat} = parsedMessage
87 | setChats((prevChats) => {
88 | // Create a new chat object
89 | const newChat = { username, message:chat };
90 |
91 | // Return the updated chats array
92 | return [...prevChats, newChat];
93 | });
94 | }
95 | else if(parsedMessage.Title === "lang-change"){
96 | const { lang } = parsedMessage
97 | setLanguage(lang)
98 | }
99 | else if(parsedMessage.Title === "Code-change"){
100 | const { code } = parsedMessage
101 | setCode(code)
102 | }
103 | else if(parsedMessage.Title === "Submit-clicked"){
104 | setSubmitClicked(true);
105 | }
106 | else if(parsedMessage.Title === "Result"){
107 | setResult(parsedMessage)
108 | setSubmitClicked(false)
109 | setIsModalOpen(true);
110 | }
111 | else if(parsedMessage.Title === "No-worker"){
112 | setSubmitClicked(false)
113 | alert("Code cannot be processed now cause it requires a continiously running worker service whcih is expensive 😅😅, if you want to, you can clone the repo and run worker process locally!!")
114 | }
115 | else if(parsedMessage.Title === "error"){
116 | setSubmitClicked(false)
117 | alert("Error processing code as of now, retry or check code for errors!")
118 | }
119 | }
120 | setSocket(newSocket)
121 | return () => newSocket.close();
122 | },[])
123 |
124 | const { isOpen: isLeftOpen, onOpen: onLeftOpen, onClose: onLeftClose } = useDisclosure();
125 | const { isOpen: isRightOpen, onOpen: onRightOpen, onClose: onRightClose } = useDisclosure();
126 | const isLargeScreen = useBreakpointValue({ base: false, md: true });
127 |
128 |
129 |
130 |
131 | const getLanguageExtension = (lang:string) => {
132 | switch (lang) {
133 | case 'javascript':
134 | return javascript({ jsx: true });
135 | case 'java':
136 | return java();
137 | case 'cpp':
138 | return cpp();
139 | case 'python':
140 | return python();
141 | default:
142 | return javascript({ jsx: true });
143 | }
144 | };
145 |
146 | const onLeave = () => {
147 | //fire websocket event
148 | if(users.length==1){
149 | const confirmation = window.confirm(
150 | "You are the last user in this room. If you leave, all data will be deleted. Do you want to proceed?"
151 | );
152 | if(!confirmation) return;
153 | }
154 | const msg = {
155 | Title : "User-left",
156 | roomId,
157 | username
158 | }
159 | socket?.send(JSON.stringify(msg))
160 | setRoomID("")
161 | Navigate("/join")
162 | }
163 |
164 | const handleCodeChange = (val:string) => {
165 | //fire websocket event
166 | const msg = {
167 | Title: "Code-change",
168 | roomId,
169 | code:val
170 | }
171 | socket?.send(JSON.stringify(msg))
172 | setCode(val)
173 | }
174 |
175 | const handleLangChange = (val:string) => {
176 | //fire websocket event
177 | const msg = {
178 | Title: "lang-change",
179 | roomId,
180 | lang:val
181 | }
182 | socket?.send(JSON.stringify(msg))
183 | }
184 |
185 | const onSubmit = () => {
186 | //make a ws req to server, send the code there, subscribe to the roomid on pub-sub
187 | const msg = {
188 | Title : "Submitted",
189 | roomId,
190 | language,
191 | code
192 | }
193 | socket?.send(JSON.stringify(msg))
194 | }
195 |
196 | function addChat(message:string){
197 | //fire websocket event
198 | const msg = {
199 | Title : "New-chat",
200 | roomId,
201 | username,
202 | chat:message
203 | }
204 | socket?.send(JSON.stringify(msg))
205 | }
206 |
207 |
208 | return (
209 |
210 |
211 | {/* Left Sidebar for large screens */}
212 | {isLargeScreen && (
213 |
214 | Members
215 |
216 |
217 | )}
218 | {/* Left Sidebar Drawer */}
219 | {!isLargeScreen && (
220 |
221 |
222 |
223 |
224 | Members
225 |
226 |
227 |
228 |
229 |
230 | )}
231 |
232 | {/* Main Content */}
233 |
234 | {/* Header Bar */}
235 |
236 |
237 |
238 |
239 | {result && }
240 |
241 | { result && {setIsModalOpen(false)}} resultMessage={result}/> }
242 |
243 |
244 |
250 | <>
251 | {submitClicked ? (
252 | ) :
253 | (
254 | )}
255 | >
256 |
257 |
258 |
259 | {roomName}
260 |
261 |
262 | {/* Sidebar Icons */}
263 | {!isLargeScreen && (
264 | <>
265 | }
267 | aria-label="Members"
268 | display={{ base: 'block', md: 'none' }}
269 | position="absolute"
270 | left="4"
271 | onClick={onLeftOpen}
272 | />
273 | }
275 | aria-label="Chats"
276 | display={{ base: 'block', md: 'none' }}
277 | position="absolute"
278 | right="4"
279 | onClick={onRightOpen}
280 | />
281 | >
282 | )}
283 |
284 |
285 | {/* editor here */}
286 | {handleCodeChange(val)}}
289 | height={useBreakpointValue({ base: '80vh', lg:"70vh", md: '60vh', sm: '50vh' })}
290 | width={useBreakpointValue({ base: '100vh', lg:"90vh", md: '80vh', sm: '70vh' })}
291 | extensions={[getLanguageExtension(language)]}
292 | theme={"dark"}
293 | />
294 |
295 |
296 |
297 | {/* Right Sidebar Drawer */}
298 | {!isLargeScreen && (
299 |
300 |
301 |
302 |
303 | Chats
304 |
305 |
306 |
307 |
308 |
309 | )}
310 |
311 | {/* Right Sidebar for large screens */}
312 | {isLargeScreen && (
313 |
314 | Chats
315 |
316 |
317 | )}
318 |
319 | );
320 | }
321 |
322 | export default Room
--------------------------------------------------------------------------------
/Worker/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "worker",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "worker",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@types/node": "^20.12.12",
13 | "axios": "^1.7.2",
14 | "dotenv": "^16.4.5",
15 | "node-fetch": "^3.3.2",
16 | "redis": "^4.6.14"
17 | },
18 | "devDependencies": {
19 | "typescript": "^5.4.5"
20 | }
21 | },
22 | "node_modules/@redis/bloom": {
23 | "version": "1.2.0",
24 | "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
25 | "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
26 | "peerDependencies": {
27 | "@redis/client": "^1.0.0"
28 | }
29 | },
30 | "node_modules/@redis/client": {
31 | "version": "1.5.16",
32 | "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.16.tgz",
33 | "integrity": "sha512-X1a3xQ5kEMvTib5fBrHKh6Y+pXbeKXqziYuxOUo1ojQNECg4M5Etd1qqyhMap+lFUOAh8S7UYevgJHOm4A+NOg==",
34 | "dependencies": {
35 | "cluster-key-slot": "1.1.2",
36 | "generic-pool": "3.9.0",
37 | "yallist": "4.0.0"
38 | },
39 | "engines": {
40 | "node": ">=14"
41 | }
42 | },
43 | "node_modules/@redis/graph": {
44 | "version": "1.1.1",
45 | "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz",
46 | "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==",
47 | "peerDependencies": {
48 | "@redis/client": "^1.0.0"
49 | }
50 | },
51 | "node_modules/@redis/json": {
52 | "version": "1.0.6",
53 | "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.6.tgz",
54 | "integrity": "sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw==",
55 | "peerDependencies": {
56 | "@redis/client": "^1.0.0"
57 | }
58 | },
59 | "node_modules/@redis/search": {
60 | "version": "1.1.6",
61 | "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.6.tgz",
62 | "integrity": "sha512-mZXCxbTYKBQ3M2lZnEddwEAks0Kc7nauire8q20oA0oA/LoA+E/b5Y5KZn232ztPb1FkIGqo12vh3Lf+Vw5iTw==",
63 | "peerDependencies": {
64 | "@redis/client": "^1.0.0"
65 | }
66 | },
67 | "node_modules/@redis/time-series": {
68 | "version": "1.0.5",
69 | "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.5.tgz",
70 | "integrity": "sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg==",
71 | "peerDependencies": {
72 | "@redis/client": "^1.0.0"
73 | }
74 | },
75 | "node_modules/@types/node": {
76 | "version": "20.12.12",
77 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
78 | "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
79 | "dependencies": {
80 | "undici-types": "~5.26.4"
81 | }
82 | },
83 | "node_modules/asynckit": {
84 | "version": "0.4.0",
85 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
86 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
87 | },
88 | "node_modules/axios": {
89 | "version": "1.7.2",
90 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
91 | "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
92 | "dependencies": {
93 | "follow-redirects": "^1.15.6",
94 | "form-data": "^4.0.0",
95 | "proxy-from-env": "^1.1.0"
96 | }
97 | },
98 | "node_modules/cluster-key-slot": {
99 | "version": "1.1.2",
100 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
101 | "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
102 | "engines": {
103 | "node": ">=0.10.0"
104 | }
105 | },
106 | "node_modules/combined-stream": {
107 | "version": "1.0.8",
108 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
109 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
110 | "dependencies": {
111 | "delayed-stream": "~1.0.0"
112 | },
113 | "engines": {
114 | "node": ">= 0.8"
115 | }
116 | },
117 | "node_modules/data-uri-to-buffer": {
118 | "version": "4.0.1",
119 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
120 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
121 | "engines": {
122 | "node": ">= 12"
123 | }
124 | },
125 | "node_modules/delayed-stream": {
126 | "version": "1.0.0",
127 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
128 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
129 | "engines": {
130 | "node": ">=0.4.0"
131 | }
132 | },
133 | "node_modules/dotenv": {
134 | "version": "16.4.5",
135 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
136 | "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
137 | "engines": {
138 | "node": ">=12"
139 | },
140 | "funding": {
141 | "url": "https://dotenvx.com"
142 | }
143 | },
144 | "node_modules/fetch-blob": {
145 | "version": "3.2.0",
146 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
147 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
148 | "funding": [
149 | {
150 | "type": "github",
151 | "url": "https://github.com/sponsors/jimmywarting"
152 | },
153 | {
154 | "type": "paypal",
155 | "url": "https://paypal.me/jimmywarting"
156 | }
157 | ],
158 | "dependencies": {
159 | "node-domexception": "^1.0.0",
160 | "web-streams-polyfill": "^3.0.3"
161 | },
162 | "engines": {
163 | "node": "^12.20 || >= 14.13"
164 | }
165 | },
166 | "node_modules/follow-redirects": {
167 | "version": "1.15.6",
168 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
169 | "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
170 | "funding": [
171 | {
172 | "type": "individual",
173 | "url": "https://github.com/sponsors/RubenVerborgh"
174 | }
175 | ],
176 | "engines": {
177 | "node": ">=4.0"
178 | },
179 | "peerDependenciesMeta": {
180 | "debug": {
181 | "optional": true
182 | }
183 | }
184 | },
185 | "node_modules/form-data": {
186 | "version": "4.0.0",
187 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
188 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
189 | "dependencies": {
190 | "asynckit": "^0.4.0",
191 | "combined-stream": "^1.0.8",
192 | "mime-types": "^2.1.12"
193 | },
194 | "engines": {
195 | "node": ">= 6"
196 | }
197 | },
198 | "node_modules/formdata-polyfill": {
199 | "version": "4.0.10",
200 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
201 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
202 | "dependencies": {
203 | "fetch-blob": "^3.1.2"
204 | },
205 | "engines": {
206 | "node": ">=12.20.0"
207 | }
208 | },
209 | "node_modules/generic-pool": {
210 | "version": "3.9.0",
211 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
212 | "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
213 | "engines": {
214 | "node": ">= 4"
215 | }
216 | },
217 | "node_modules/mime-db": {
218 | "version": "1.52.0",
219 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
220 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
221 | "engines": {
222 | "node": ">= 0.6"
223 | }
224 | },
225 | "node_modules/mime-types": {
226 | "version": "2.1.35",
227 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
228 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
229 | "dependencies": {
230 | "mime-db": "1.52.0"
231 | },
232 | "engines": {
233 | "node": ">= 0.6"
234 | }
235 | },
236 | "node_modules/node-domexception": {
237 | "version": "1.0.0",
238 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
239 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
240 | "funding": [
241 | {
242 | "type": "github",
243 | "url": "https://github.com/sponsors/jimmywarting"
244 | },
245 | {
246 | "type": "github",
247 | "url": "https://paypal.me/jimmywarting"
248 | }
249 | ],
250 | "engines": {
251 | "node": ">=10.5.0"
252 | }
253 | },
254 | "node_modules/node-fetch": {
255 | "version": "3.3.2",
256 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
257 | "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
258 | "dependencies": {
259 | "data-uri-to-buffer": "^4.0.0",
260 | "fetch-blob": "^3.1.4",
261 | "formdata-polyfill": "^4.0.10"
262 | },
263 | "engines": {
264 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
265 | },
266 | "funding": {
267 | "type": "opencollective",
268 | "url": "https://opencollective.com/node-fetch"
269 | }
270 | },
271 | "node_modules/proxy-from-env": {
272 | "version": "1.1.0",
273 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
274 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
275 | },
276 | "node_modules/redis": {
277 | "version": "4.6.14",
278 | "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.14.tgz",
279 | "integrity": "sha512-GrNg/e33HtsQwNXL7kJT+iNFPSwE1IPmd7wzV3j4f2z0EYxZfZE7FVTmUysgAtqQQtg5NXF5SNLR9OdO/UHOfw==",
280 | "dependencies": {
281 | "@redis/bloom": "1.2.0",
282 | "@redis/client": "1.5.16",
283 | "@redis/graph": "1.1.1",
284 | "@redis/json": "1.0.6",
285 | "@redis/search": "1.1.6",
286 | "@redis/time-series": "1.0.5"
287 | }
288 | },
289 | "node_modules/typescript": {
290 | "version": "5.4.5",
291 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
292 | "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
293 | "dev": true,
294 | "bin": {
295 | "tsc": "bin/tsc",
296 | "tsserver": "bin/tsserver"
297 | },
298 | "engines": {
299 | "node": ">=14.17"
300 | }
301 | },
302 | "node_modules/undici-types": {
303 | "version": "5.26.5",
304 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
305 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
306 | },
307 | "node_modules/web-streams-polyfill": {
308 | "version": "3.3.3",
309 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
310 | "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
311 | "engines": {
312 | "node": ">= 8"
313 | }
314 | },
315 | "node_modules/yallist": {
316 | "version": "4.0.0",
317 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
318 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
319 | }
320 | }
321 | }
322 |
--------------------------------------------------------------------------------
/Server/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "server",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@types/bcrypt": "^5.0.2",
13 | "@types/express": "^4.17.21",
14 | "@types/ws": "^8.5.10",
15 | "bcrypt": "^5.1.1",
16 | "dotenv": "^16.4.5",
17 | "express": "^4.19.2",
18 | "mongoose": "^8.4.0",
19 | "redis": "^4.6.14",
20 | "ws": "^8.17.0"
21 | },
22 | "devDependencies": {
23 | "@types/bcrypt": "^5.0.2",
24 | "@types/cors": "^2.8.17",
25 | "cors": "^2.8.5",
26 | "typescript": "^5.4.5"
27 | }
28 | },
29 | "node_modules/@mapbox/node-pre-gyp": {
30 | "version": "1.0.11",
31 | "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
32 | "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
33 | "dependencies": {
34 | "detect-libc": "^2.0.0",
35 | "https-proxy-agent": "^5.0.0",
36 | "make-dir": "^3.1.0",
37 | "node-fetch": "^2.6.7",
38 | "nopt": "^5.0.0",
39 | "npmlog": "^5.0.1",
40 | "rimraf": "^3.0.2",
41 | "semver": "^7.3.5",
42 | "tar": "^6.1.11"
43 | },
44 | "bin": {
45 | "node-pre-gyp": "bin/node-pre-gyp"
46 | }
47 | },
48 | "node_modules/@mongodb-js/saslprep": {
49 | "version": "1.1.7",
50 | "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz",
51 | "integrity": "sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q==",
52 | "dependencies": {
53 | "sparse-bitfield": "^3.0.3"
54 | }
55 | },
56 | "node_modules/@redis/bloom": {
57 | "version": "1.2.0",
58 | "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
59 | "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
60 | "peerDependencies": {
61 | "@redis/client": "^1.0.0"
62 | }
63 | },
64 | "node_modules/@redis/client": {
65 | "version": "1.5.16",
66 | "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.16.tgz",
67 | "integrity": "sha512-X1a3xQ5kEMvTib5fBrHKh6Y+pXbeKXqziYuxOUo1ojQNECg4M5Etd1qqyhMap+lFUOAh8S7UYevgJHOm4A+NOg==",
68 | "dependencies": {
69 | "cluster-key-slot": "1.1.2",
70 | "generic-pool": "3.9.0",
71 | "yallist": "4.0.0"
72 | },
73 | "engines": {
74 | "node": ">=14"
75 | }
76 | },
77 | "node_modules/@redis/graph": {
78 | "version": "1.1.1",
79 | "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz",
80 | "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==",
81 | "peerDependencies": {
82 | "@redis/client": "^1.0.0"
83 | }
84 | },
85 | "node_modules/@redis/json": {
86 | "version": "1.0.6",
87 | "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.6.tgz",
88 | "integrity": "sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw==",
89 | "peerDependencies": {
90 | "@redis/client": "^1.0.0"
91 | }
92 | },
93 | "node_modules/@redis/search": {
94 | "version": "1.1.6",
95 | "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.6.tgz",
96 | "integrity": "sha512-mZXCxbTYKBQ3M2lZnEddwEAks0Kc7nauire8q20oA0oA/LoA+E/b5Y5KZn232ztPb1FkIGqo12vh3Lf+Vw5iTw==",
97 | "peerDependencies": {
98 | "@redis/client": "^1.0.0"
99 | }
100 | },
101 | "node_modules/@redis/time-series": {
102 | "version": "1.0.5",
103 | "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.5.tgz",
104 | "integrity": "sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg==",
105 | "peerDependencies": {
106 | "@redis/client": "^1.0.0"
107 | }
108 | },
109 | "node_modules/@types/bcrypt": {
110 | "version": "5.0.2",
111 | "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz",
112 | "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==",
113 | "dev": true,
114 | "dependencies": {
115 | "@types/node": "*"
116 | }
117 | },
118 | "node_modules/@types/body-parser": {
119 | "version": "1.19.5",
120 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
121 | "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
122 | "dependencies": {
123 | "@types/connect": "*",
124 | "@types/node": "*"
125 | }
126 | },
127 | "node_modules/@types/connect": {
128 | "version": "3.4.38",
129 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
130 | "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
131 | "dependencies": {
132 | "@types/node": "*"
133 | }
134 | },
135 | "node_modules/@types/cors": {
136 | "version": "2.8.17",
137 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
138 | "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
139 | "dev": true,
140 | "dependencies": {
141 | "@types/node": "*"
142 | }
143 | },
144 | "node_modules/@types/express": {
145 | "version": "4.17.21",
146 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
147 | "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
148 | "dependencies": {
149 | "@types/body-parser": "*",
150 | "@types/express-serve-static-core": "^4.17.33",
151 | "@types/qs": "*",
152 | "@types/serve-static": "*"
153 | }
154 | },
155 | "node_modules/@types/express-serve-static-core": {
156 | "version": "4.19.0",
157 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz",
158 | "integrity": "sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==",
159 | "dependencies": {
160 | "@types/node": "*",
161 | "@types/qs": "*",
162 | "@types/range-parser": "*",
163 | "@types/send": "*"
164 | }
165 | },
166 | "node_modules/@types/http-errors": {
167 | "version": "2.0.4",
168 | "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
169 | "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA=="
170 | },
171 | "node_modules/@types/mime": {
172 | "version": "1.3.5",
173 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
174 | "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
175 | },
176 | "node_modules/@types/node": {
177 | "version": "20.12.11",
178 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz",
179 | "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==",
180 | "dependencies": {
181 | "undici-types": "~5.26.4"
182 | }
183 | },
184 | "node_modules/@types/qs": {
185 | "version": "6.9.15",
186 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz",
187 | "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg=="
188 | },
189 | "node_modules/@types/range-parser": {
190 | "version": "1.2.7",
191 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
192 | "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="
193 | },
194 | "node_modules/@types/send": {
195 | "version": "0.17.4",
196 | "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
197 | "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
198 | "dependencies": {
199 | "@types/mime": "^1",
200 | "@types/node": "*"
201 | }
202 | },
203 | "node_modules/@types/serve-static": {
204 | "version": "1.15.7",
205 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
206 | "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
207 | "dependencies": {
208 | "@types/http-errors": "*",
209 | "@types/node": "*",
210 | "@types/send": "*"
211 | }
212 | },
213 | "node_modules/@types/webidl-conversions": {
214 | "version": "7.0.3",
215 | "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
216 | "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
217 | },
218 | "node_modules/@types/whatwg-url": {
219 | "version": "11.0.5",
220 | "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
221 | "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
222 | "dependencies": {
223 | "@types/webidl-conversions": "*"
224 | }
225 | },
226 | "node_modules/@types/ws": {
227 | "version": "8.5.10",
228 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
229 | "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
230 | "dependencies": {
231 | "@types/node": "*"
232 | }
233 | },
234 | "node_modules/abbrev": {
235 | "version": "1.1.1",
236 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
237 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
238 | },
239 | "node_modules/accepts": {
240 | "version": "1.3.8",
241 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
242 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
243 | "dependencies": {
244 | "mime-types": "~2.1.34",
245 | "negotiator": "0.6.3"
246 | },
247 | "engines": {
248 | "node": ">= 0.6"
249 | }
250 | },
251 | "node_modules/agent-base": {
252 | "version": "6.0.2",
253 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
254 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
255 | "dependencies": {
256 | "debug": "4"
257 | },
258 | "engines": {
259 | "node": ">= 6.0.0"
260 | }
261 | },
262 | "node_modules/agent-base/node_modules/debug": {
263 | "version": "4.3.5",
264 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
265 | "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
266 | "dependencies": {
267 | "ms": "2.1.2"
268 | },
269 | "engines": {
270 | "node": ">=6.0"
271 | },
272 | "peerDependenciesMeta": {
273 | "supports-color": {
274 | "optional": true
275 | }
276 | }
277 | },
278 | "node_modules/agent-base/node_modules/ms": {
279 | "version": "2.1.2",
280 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
281 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
282 | },
283 | "node_modules/ansi-regex": {
284 | "version": "5.0.1",
285 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
286 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
287 | "engines": {
288 | "node": ">=8"
289 | }
290 | },
291 | "node_modules/aproba": {
292 | "version": "2.0.0",
293 | "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
294 | "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
295 | },
296 | "node_modules/are-we-there-yet": {
297 | "version": "2.0.0",
298 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
299 | "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
300 | "deprecated": "This package is no longer supported.",
301 | "dependencies": {
302 | "delegates": "^1.0.0",
303 | "readable-stream": "^3.6.0"
304 | },
305 | "engines": {
306 | "node": ">=10"
307 | }
308 | },
309 | "node_modules/array-flatten": {
310 | "version": "1.1.1",
311 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
312 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
313 | },
314 | "node_modules/balanced-match": {
315 | "version": "1.0.2",
316 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
317 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
318 | },
319 | "node_modules/bcrypt": {
320 | "version": "5.1.1",
321 | "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
322 | "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==",
323 | "hasInstallScript": true,
324 | "dependencies": {
325 | "@mapbox/node-pre-gyp": "^1.0.11",
326 | "node-addon-api": "^5.0.0"
327 | },
328 | "engines": {
329 | "node": ">= 10.0.0"
330 | }
331 | },
332 | "node_modules/body-parser": {
333 | "version": "1.20.2",
334 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
335 | "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
336 | "dependencies": {
337 | "bytes": "3.1.2",
338 | "content-type": "~1.0.5",
339 | "debug": "2.6.9",
340 | "depd": "2.0.0",
341 | "destroy": "1.2.0",
342 | "http-errors": "2.0.0",
343 | "iconv-lite": "0.4.24",
344 | "on-finished": "2.4.1",
345 | "qs": "6.11.0",
346 | "raw-body": "2.5.2",
347 | "type-is": "~1.6.18",
348 | "unpipe": "1.0.0"
349 | },
350 | "engines": {
351 | "node": ">= 0.8",
352 | "npm": "1.2.8000 || >= 1.4.16"
353 | }
354 | },
355 | "node_modules/brace-expansion": {
356 | "version": "1.1.11",
357 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
358 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
359 | "dependencies": {
360 | "balanced-match": "^1.0.0",
361 | "concat-map": "0.0.1"
362 | }
363 | },
364 | "node_modules/bson": {
365 | "version": "6.7.0",
366 | "resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz",
367 | "integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==",
368 | "engines": {
369 | "node": ">=16.20.1"
370 | }
371 | },
372 | "node_modules/bytes": {
373 | "version": "3.1.2",
374 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
375 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
376 | "engines": {
377 | "node": ">= 0.8"
378 | }
379 | },
380 | "node_modules/call-bind": {
381 | "version": "1.0.7",
382 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
383 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
384 | "dependencies": {
385 | "es-define-property": "^1.0.0",
386 | "es-errors": "^1.3.0",
387 | "function-bind": "^1.1.2",
388 | "get-intrinsic": "^1.2.4",
389 | "set-function-length": "^1.2.1"
390 | },
391 | "engines": {
392 | "node": ">= 0.4"
393 | },
394 | "funding": {
395 | "url": "https://github.com/sponsors/ljharb"
396 | }
397 | },
398 | "node_modules/chownr": {
399 | "version": "2.0.0",
400 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
401 | "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
402 | "engines": {
403 | "node": ">=10"
404 | }
405 | },
406 | "node_modules/cluster-key-slot": {
407 | "version": "1.1.2",
408 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
409 | "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
410 | "engines": {
411 | "node": ">=0.10.0"
412 | }
413 | },
414 | "node_modules/color-support": {
415 | "version": "1.1.3",
416 | "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
417 | "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
418 | "bin": {
419 | "color-support": "bin.js"
420 | }
421 | },
422 | "node_modules/concat-map": {
423 | "version": "0.0.1",
424 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
425 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
426 | },
427 | "node_modules/console-control-strings": {
428 | "version": "1.1.0",
429 | "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
430 | "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
431 | },
432 | "node_modules/content-disposition": {
433 | "version": "0.5.4",
434 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
435 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
436 | "dependencies": {
437 | "safe-buffer": "5.2.1"
438 | },
439 | "engines": {
440 | "node": ">= 0.6"
441 | }
442 | },
443 | "node_modules/content-type": {
444 | "version": "1.0.5",
445 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
446 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
447 | "engines": {
448 | "node": ">= 0.6"
449 | }
450 | },
451 | "node_modules/cookie": {
452 | "version": "0.6.0",
453 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
454 | "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
455 | "engines": {
456 | "node": ">= 0.6"
457 | }
458 | },
459 | "node_modules/cookie-signature": {
460 | "version": "1.0.6",
461 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
462 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
463 | },
464 | "node_modules/cors": {
465 | "version": "2.8.5",
466 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
467 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
468 | "dev": true,
469 | "dependencies": {
470 | "object-assign": "^4",
471 | "vary": "^1"
472 | },
473 | "engines": {
474 | "node": ">= 0.10"
475 | }
476 | },
477 | "node_modules/debug": {
478 | "version": "2.6.9",
479 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
480 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
481 | "dependencies": {
482 | "ms": "2.0.0"
483 | }
484 | },
485 | "node_modules/define-data-property": {
486 | "version": "1.1.4",
487 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
488 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
489 | "dependencies": {
490 | "es-define-property": "^1.0.0",
491 | "es-errors": "^1.3.0",
492 | "gopd": "^1.0.1"
493 | },
494 | "engines": {
495 | "node": ">= 0.4"
496 | },
497 | "funding": {
498 | "url": "https://github.com/sponsors/ljharb"
499 | }
500 | },
501 | "node_modules/delegates": {
502 | "version": "1.0.0",
503 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
504 | "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
505 | },
506 | "node_modules/depd": {
507 | "version": "2.0.0",
508 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
509 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
510 | "engines": {
511 | "node": ">= 0.8"
512 | }
513 | },
514 | "node_modules/destroy": {
515 | "version": "1.2.0",
516 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
517 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
518 | "engines": {
519 | "node": ">= 0.8",
520 | "npm": "1.2.8000 || >= 1.4.16"
521 | }
522 | },
523 | "node_modules/detect-libc": {
524 | "version": "2.0.3",
525 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
526 | "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
527 | "engines": {
528 | "node": ">=8"
529 | }
530 | },
531 | "node_modules/dotenv": {
532 | "version": "16.4.5",
533 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
534 | "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
535 | "engines": {
536 | "node": ">=12"
537 | },
538 | "funding": {
539 | "url": "https://dotenvx.com"
540 | }
541 | },
542 | "node_modules/ee-first": {
543 | "version": "1.1.1",
544 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
545 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
546 | },
547 | "node_modules/emoji-regex": {
548 | "version": "8.0.0",
549 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
550 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
551 | },
552 | "node_modules/encodeurl": {
553 | "version": "1.0.2",
554 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
555 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
556 | "engines": {
557 | "node": ">= 0.8"
558 | }
559 | },
560 | "node_modules/es-define-property": {
561 | "version": "1.0.0",
562 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
563 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
564 | "dependencies": {
565 | "get-intrinsic": "^1.2.4"
566 | },
567 | "engines": {
568 | "node": ">= 0.4"
569 | }
570 | },
571 | "node_modules/es-errors": {
572 | "version": "1.3.0",
573 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
574 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
575 | "engines": {
576 | "node": ">= 0.4"
577 | }
578 | },
579 | "node_modules/escape-html": {
580 | "version": "1.0.3",
581 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
582 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
583 | },
584 | "node_modules/etag": {
585 | "version": "1.8.1",
586 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
587 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
588 | "engines": {
589 | "node": ">= 0.6"
590 | }
591 | },
592 | "node_modules/express": {
593 | "version": "4.19.2",
594 | "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
595 | "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
596 | "dependencies": {
597 | "accepts": "~1.3.8",
598 | "array-flatten": "1.1.1",
599 | "body-parser": "1.20.2",
600 | "content-disposition": "0.5.4",
601 | "content-type": "~1.0.4",
602 | "cookie": "0.6.0",
603 | "cookie-signature": "1.0.6",
604 | "debug": "2.6.9",
605 | "depd": "2.0.0",
606 | "encodeurl": "~1.0.2",
607 | "escape-html": "~1.0.3",
608 | "etag": "~1.8.1",
609 | "finalhandler": "1.2.0",
610 | "fresh": "0.5.2",
611 | "http-errors": "2.0.0",
612 | "merge-descriptors": "1.0.1",
613 | "methods": "~1.1.2",
614 | "on-finished": "2.4.1",
615 | "parseurl": "~1.3.3",
616 | "path-to-regexp": "0.1.7",
617 | "proxy-addr": "~2.0.7",
618 | "qs": "6.11.0",
619 | "range-parser": "~1.2.1",
620 | "safe-buffer": "5.2.1",
621 | "send": "0.18.0",
622 | "serve-static": "1.15.0",
623 | "setprototypeof": "1.2.0",
624 | "statuses": "2.0.1",
625 | "type-is": "~1.6.18",
626 | "utils-merge": "1.0.1",
627 | "vary": "~1.1.2"
628 | },
629 | "engines": {
630 | "node": ">= 0.10.0"
631 | }
632 | },
633 | "node_modules/finalhandler": {
634 | "version": "1.2.0",
635 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
636 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
637 | "dependencies": {
638 | "debug": "2.6.9",
639 | "encodeurl": "~1.0.2",
640 | "escape-html": "~1.0.3",
641 | "on-finished": "2.4.1",
642 | "parseurl": "~1.3.3",
643 | "statuses": "2.0.1",
644 | "unpipe": "~1.0.0"
645 | },
646 | "engines": {
647 | "node": ">= 0.8"
648 | }
649 | },
650 | "node_modules/forwarded": {
651 | "version": "0.2.0",
652 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
653 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
654 | "engines": {
655 | "node": ">= 0.6"
656 | }
657 | },
658 | "node_modules/fresh": {
659 | "version": "0.5.2",
660 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
661 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
662 | "engines": {
663 | "node": ">= 0.6"
664 | }
665 | },
666 | "node_modules/fs-minipass": {
667 | "version": "2.1.0",
668 | "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
669 | "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
670 | "dependencies": {
671 | "minipass": "^3.0.0"
672 | },
673 | "engines": {
674 | "node": ">= 8"
675 | }
676 | },
677 | "node_modules/fs-minipass/node_modules/minipass": {
678 | "version": "3.3.6",
679 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
680 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
681 | "dependencies": {
682 | "yallist": "^4.0.0"
683 | },
684 | "engines": {
685 | "node": ">=8"
686 | }
687 | },
688 | "node_modules/fs.realpath": {
689 | "version": "1.0.0",
690 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
691 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
692 | },
693 | "node_modules/function-bind": {
694 | "version": "1.1.2",
695 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
696 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
697 | "funding": {
698 | "url": "https://github.com/sponsors/ljharb"
699 | }
700 | },
701 | "node_modules/gauge": {
702 | "version": "3.0.2",
703 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
704 | "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
705 | "deprecated": "This package is no longer supported.",
706 | "dependencies": {
707 | "aproba": "^1.0.3 || ^2.0.0",
708 | "color-support": "^1.1.2",
709 | "console-control-strings": "^1.0.0",
710 | "has-unicode": "^2.0.1",
711 | "object-assign": "^4.1.1",
712 | "signal-exit": "^3.0.0",
713 | "string-width": "^4.2.3",
714 | "strip-ansi": "^6.0.1",
715 | "wide-align": "^1.1.2"
716 | },
717 | "engines": {
718 | "node": ">=10"
719 | }
720 | },
721 | "node_modules/generic-pool": {
722 | "version": "3.9.0",
723 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
724 | "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
725 | "engines": {
726 | "node": ">= 4"
727 | }
728 | },
729 | "node_modules/get-intrinsic": {
730 | "version": "1.2.4",
731 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
732 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
733 | "dependencies": {
734 | "es-errors": "^1.3.0",
735 | "function-bind": "^1.1.2",
736 | "has-proto": "^1.0.1",
737 | "has-symbols": "^1.0.3",
738 | "hasown": "^2.0.0"
739 | },
740 | "engines": {
741 | "node": ">= 0.4"
742 | },
743 | "funding": {
744 | "url": "https://github.com/sponsors/ljharb"
745 | }
746 | },
747 | "node_modules/glob": {
748 | "version": "7.2.3",
749 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
750 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
751 | "deprecated": "Glob versions prior to v9 are no longer supported",
752 | "dependencies": {
753 | "fs.realpath": "^1.0.0",
754 | "inflight": "^1.0.4",
755 | "inherits": "2",
756 | "minimatch": "^3.1.1",
757 | "once": "^1.3.0",
758 | "path-is-absolute": "^1.0.0"
759 | },
760 | "engines": {
761 | "node": "*"
762 | },
763 | "funding": {
764 | "url": "https://github.com/sponsors/isaacs"
765 | }
766 | },
767 | "node_modules/gopd": {
768 | "version": "1.0.1",
769 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
770 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
771 | "dependencies": {
772 | "get-intrinsic": "^1.1.3"
773 | },
774 | "funding": {
775 | "url": "https://github.com/sponsors/ljharb"
776 | }
777 | },
778 | "node_modules/has-property-descriptors": {
779 | "version": "1.0.2",
780 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
781 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
782 | "dependencies": {
783 | "es-define-property": "^1.0.0"
784 | },
785 | "funding": {
786 | "url": "https://github.com/sponsors/ljharb"
787 | }
788 | },
789 | "node_modules/has-proto": {
790 | "version": "1.0.3",
791 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
792 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
793 | "engines": {
794 | "node": ">= 0.4"
795 | },
796 | "funding": {
797 | "url": "https://github.com/sponsors/ljharb"
798 | }
799 | },
800 | "node_modules/has-symbols": {
801 | "version": "1.0.3",
802 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
803 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
804 | "engines": {
805 | "node": ">= 0.4"
806 | },
807 | "funding": {
808 | "url": "https://github.com/sponsors/ljharb"
809 | }
810 | },
811 | "node_modules/has-unicode": {
812 | "version": "2.0.1",
813 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
814 | "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
815 | },
816 | "node_modules/hasown": {
817 | "version": "2.0.2",
818 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
819 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
820 | "dependencies": {
821 | "function-bind": "^1.1.2"
822 | },
823 | "engines": {
824 | "node": ">= 0.4"
825 | }
826 | },
827 | "node_modules/http-errors": {
828 | "version": "2.0.0",
829 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
830 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
831 | "dependencies": {
832 | "depd": "2.0.0",
833 | "inherits": "2.0.4",
834 | "setprototypeof": "1.2.0",
835 | "statuses": "2.0.1",
836 | "toidentifier": "1.0.1"
837 | },
838 | "engines": {
839 | "node": ">= 0.8"
840 | }
841 | },
842 | "node_modules/https-proxy-agent": {
843 | "version": "5.0.1",
844 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
845 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
846 | "dependencies": {
847 | "agent-base": "6",
848 | "debug": "4"
849 | },
850 | "engines": {
851 | "node": ">= 6"
852 | }
853 | },
854 | "node_modules/https-proxy-agent/node_modules/debug": {
855 | "version": "4.3.5",
856 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
857 | "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
858 | "dependencies": {
859 | "ms": "2.1.2"
860 | },
861 | "engines": {
862 | "node": ">=6.0"
863 | },
864 | "peerDependenciesMeta": {
865 | "supports-color": {
866 | "optional": true
867 | }
868 | }
869 | },
870 | "node_modules/https-proxy-agent/node_modules/ms": {
871 | "version": "2.1.2",
872 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
873 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
874 | },
875 | "node_modules/iconv-lite": {
876 | "version": "0.4.24",
877 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
878 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
879 | "dependencies": {
880 | "safer-buffer": ">= 2.1.2 < 3"
881 | },
882 | "engines": {
883 | "node": ">=0.10.0"
884 | }
885 | },
886 | "node_modules/inflight": {
887 | "version": "1.0.6",
888 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
889 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
890 | "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
891 | "dependencies": {
892 | "once": "^1.3.0",
893 | "wrappy": "1"
894 | }
895 | },
896 | "node_modules/inherits": {
897 | "version": "2.0.4",
898 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
899 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
900 | },
901 | "node_modules/ipaddr.js": {
902 | "version": "1.9.1",
903 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
904 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
905 | "engines": {
906 | "node": ">= 0.10"
907 | }
908 | },
909 | "node_modules/is-fullwidth-code-point": {
910 | "version": "3.0.0",
911 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
912 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
913 | "engines": {
914 | "node": ">=8"
915 | }
916 | },
917 | "node_modules/kareem": {
918 | "version": "2.6.3",
919 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz",
920 | "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==",
921 | "engines": {
922 | "node": ">=12.0.0"
923 | }
924 | },
925 | "node_modules/make-dir": {
926 | "version": "3.1.0",
927 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
928 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
929 | "dependencies": {
930 | "semver": "^6.0.0"
931 | },
932 | "engines": {
933 | "node": ">=8"
934 | },
935 | "funding": {
936 | "url": "https://github.com/sponsors/sindresorhus"
937 | }
938 | },
939 | "node_modules/make-dir/node_modules/semver": {
940 | "version": "6.3.1",
941 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
942 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
943 | "bin": {
944 | "semver": "bin/semver.js"
945 | }
946 | },
947 | "node_modules/media-typer": {
948 | "version": "0.3.0",
949 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
950 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
951 | "engines": {
952 | "node": ">= 0.6"
953 | }
954 | },
955 | "node_modules/memory-pager": {
956 | "version": "1.5.0",
957 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
958 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
959 | },
960 | "node_modules/merge-descriptors": {
961 | "version": "1.0.1",
962 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
963 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
964 | },
965 | "node_modules/methods": {
966 | "version": "1.1.2",
967 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
968 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
969 | "engines": {
970 | "node": ">= 0.6"
971 | }
972 | },
973 | "node_modules/mime": {
974 | "version": "1.6.0",
975 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
976 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
977 | "bin": {
978 | "mime": "cli.js"
979 | },
980 | "engines": {
981 | "node": ">=4"
982 | }
983 | },
984 | "node_modules/mime-db": {
985 | "version": "1.52.0",
986 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
987 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
988 | "engines": {
989 | "node": ">= 0.6"
990 | }
991 | },
992 | "node_modules/mime-types": {
993 | "version": "2.1.35",
994 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
995 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
996 | "dependencies": {
997 | "mime-db": "1.52.0"
998 | },
999 | "engines": {
1000 | "node": ">= 0.6"
1001 | }
1002 | },
1003 | "node_modules/minimatch": {
1004 | "version": "3.1.2",
1005 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1006 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1007 | "dependencies": {
1008 | "brace-expansion": "^1.1.7"
1009 | },
1010 | "engines": {
1011 | "node": "*"
1012 | }
1013 | },
1014 | "node_modules/minipass": {
1015 | "version": "5.0.0",
1016 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
1017 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
1018 | "engines": {
1019 | "node": ">=8"
1020 | }
1021 | },
1022 | "node_modules/minizlib": {
1023 | "version": "2.1.2",
1024 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
1025 | "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
1026 | "dependencies": {
1027 | "minipass": "^3.0.0",
1028 | "yallist": "^4.0.0"
1029 | },
1030 | "engines": {
1031 | "node": ">= 8"
1032 | }
1033 | },
1034 | "node_modules/minizlib/node_modules/minipass": {
1035 | "version": "3.3.6",
1036 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
1037 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
1038 | "dependencies": {
1039 | "yallist": "^4.0.0"
1040 | },
1041 | "engines": {
1042 | "node": ">=8"
1043 | }
1044 | },
1045 | "node_modules/mkdirp": {
1046 | "version": "1.0.4",
1047 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
1048 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
1049 | "bin": {
1050 | "mkdirp": "bin/cmd.js"
1051 | },
1052 | "engines": {
1053 | "node": ">=10"
1054 | }
1055 | },
1056 | "node_modules/mongodb": {
1057 | "version": "6.6.2",
1058 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.6.2.tgz",
1059 | "integrity": "sha512-ZF9Ugo2JCG/GfR7DEb4ypfyJJyiKbg5qBYKRintebj8+DNS33CyGMkWbrS9lara+u+h+yEOGSRiLhFO/g1s1aw==",
1060 | "dependencies": {
1061 | "@mongodb-js/saslprep": "^1.1.5",
1062 | "bson": "^6.7.0",
1063 | "mongodb-connection-string-url": "^3.0.0"
1064 | },
1065 | "engines": {
1066 | "node": ">=16.20.1"
1067 | },
1068 | "peerDependencies": {
1069 | "@aws-sdk/credential-providers": "^3.188.0",
1070 | "@mongodb-js/zstd": "^1.1.0",
1071 | "gcp-metadata": "^5.2.0",
1072 | "kerberos": "^2.0.1",
1073 | "mongodb-client-encryption": ">=6.0.0 <7",
1074 | "snappy": "^7.2.2",
1075 | "socks": "^2.7.1"
1076 | },
1077 | "peerDependenciesMeta": {
1078 | "@aws-sdk/credential-providers": {
1079 | "optional": true
1080 | },
1081 | "@mongodb-js/zstd": {
1082 | "optional": true
1083 | },
1084 | "gcp-metadata": {
1085 | "optional": true
1086 | },
1087 | "kerberos": {
1088 | "optional": true
1089 | },
1090 | "mongodb-client-encryption": {
1091 | "optional": true
1092 | },
1093 | "snappy": {
1094 | "optional": true
1095 | },
1096 | "socks": {
1097 | "optional": true
1098 | }
1099 | }
1100 | },
1101 | "node_modules/mongodb-connection-string-url": {
1102 | "version": "3.0.1",
1103 | "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz",
1104 | "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==",
1105 | "dependencies": {
1106 | "@types/whatwg-url": "^11.0.2",
1107 | "whatwg-url": "^13.0.0"
1108 | }
1109 | },
1110 | "node_modules/mongoose": {
1111 | "version": "8.4.0",
1112 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.4.0.tgz",
1113 | "integrity": "sha512-fgqRMwVEP1qgRYfh+tUe2YBBFnPO35FIg2lfFH+w9IhRGg1/ataWGIqvf/MjwM29cZ60D5vSnqtN2b8Qp0sOZA==",
1114 | "dependencies": {
1115 | "bson": "^6.7.0",
1116 | "kareem": "2.6.3",
1117 | "mongodb": "6.6.2",
1118 | "mpath": "0.9.0",
1119 | "mquery": "5.0.0",
1120 | "ms": "2.1.3",
1121 | "sift": "17.1.3"
1122 | },
1123 | "engines": {
1124 | "node": ">=16.20.1"
1125 | },
1126 | "funding": {
1127 | "type": "opencollective",
1128 | "url": "https://opencollective.com/mongoose"
1129 | }
1130 | },
1131 | "node_modules/mongoose/node_modules/ms": {
1132 | "version": "2.1.3",
1133 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1134 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1135 | },
1136 | "node_modules/mpath": {
1137 | "version": "0.9.0",
1138 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
1139 | "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
1140 | "engines": {
1141 | "node": ">=4.0.0"
1142 | }
1143 | },
1144 | "node_modules/mquery": {
1145 | "version": "5.0.0",
1146 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
1147 | "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
1148 | "dependencies": {
1149 | "debug": "4.x"
1150 | },
1151 | "engines": {
1152 | "node": ">=14.0.0"
1153 | }
1154 | },
1155 | "node_modules/mquery/node_modules/debug": {
1156 | "version": "4.3.4",
1157 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1158 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1159 | "dependencies": {
1160 | "ms": "2.1.2"
1161 | },
1162 | "engines": {
1163 | "node": ">=6.0"
1164 | },
1165 | "peerDependenciesMeta": {
1166 | "supports-color": {
1167 | "optional": true
1168 | }
1169 | }
1170 | },
1171 | "node_modules/mquery/node_modules/ms": {
1172 | "version": "2.1.2",
1173 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1174 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
1175 | },
1176 | "node_modules/ms": {
1177 | "version": "2.0.0",
1178 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1179 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
1180 | },
1181 | "node_modules/negotiator": {
1182 | "version": "0.6.3",
1183 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
1184 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
1185 | "engines": {
1186 | "node": ">= 0.6"
1187 | }
1188 | },
1189 | "node_modules/node-addon-api": {
1190 | "version": "5.1.0",
1191 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz",
1192 | "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="
1193 | },
1194 | "node_modules/node-fetch": {
1195 | "version": "2.7.0",
1196 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
1197 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
1198 | "dependencies": {
1199 | "whatwg-url": "^5.0.0"
1200 | },
1201 | "engines": {
1202 | "node": "4.x || >=6.0.0"
1203 | },
1204 | "peerDependencies": {
1205 | "encoding": "^0.1.0"
1206 | },
1207 | "peerDependenciesMeta": {
1208 | "encoding": {
1209 | "optional": true
1210 | }
1211 | }
1212 | },
1213 | "node_modules/node-fetch/node_modules/tr46": {
1214 | "version": "0.0.3",
1215 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
1216 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
1217 | },
1218 | "node_modules/node-fetch/node_modules/webidl-conversions": {
1219 | "version": "3.0.1",
1220 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
1221 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
1222 | },
1223 | "node_modules/node-fetch/node_modules/whatwg-url": {
1224 | "version": "5.0.0",
1225 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
1226 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
1227 | "dependencies": {
1228 | "tr46": "~0.0.3",
1229 | "webidl-conversions": "^3.0.0"
1230 | }
1231 | },
1232 | "node_modules/nopt": {
1233 | "version": "5.0.0",
1234 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
1235 | "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
1236 | "dependencies": {
1237 | "abbrev": "1"
1238 | },
1239 | "bin": {
1240 | "nopt": "bin/nopt.js"
1241 | },
1242 | "engines": {
1243 | "node": ">=6"
1244 | }
1245 | },
1246 | "node_modules/npmlog": {
1247 | "version": "5.0.1",
1248 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
1249 | "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
1250 | "deprecated": "This package is no longer supported.",
1251 | "dependencies": {
1252 | "are-we-there-yet": "^2.0.0",
1253 | "console-control-strings": "^1.1.0",
1254 | "gauge": "^3.0.0",
1255 | "set-blocking": "^2.0.0"
1256 | }
1257 | },
1258 | "node_modules/object-assign": {
1259 | "version": "4.1.1",
1260 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1261 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
1262 | "engines": {
1263 | "node": ">=0.10.0"
1264 | }
1265 | },
1266 | "node_modules/object-inspect": {
1267 | "version": "1.13.1",
1268 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
1269 | "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
1270 | "funding": {
1271 | "url": "https://github.com/sponsors/ljharb"
1272 | }
1273 | },
1274 | "node_modules/on-finished": {
1275 | "version": "2.4.1",
1276 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
1277 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
1278 | "dependencies": {
1279 | "ee-first": "1.1.1"
1280 | },
1281 | "engines": {
1282 | "node": ">= 0.8"
1283 | }
1284 | },
1285 | "node_modules/once": {
1286 | "version": "1.4.0",
1287 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1288 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1289 | "dependencies": {
1290 | "wrappy": "1"
1291 | }
1292 | },
1293 | "node_modules/parseurl": {
1294 | "version": "1.3.3",
1295 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1296 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
1297 | "engines": {
1298 | "node": ">= 0.8"
1299 | }
1300 | },
1301 | "node_modules/path-is-absolute": {
1302 | "version": "1.0.1",
1303 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1304 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1305 | "engines": {
1306 | "node": ">=0.10.0"
1307 | }
1308 | },
1309 | "node_modules/path-to-regexp": {
1310 | "version": "0.1.7",
1311 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
1312 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
1313 | },
1314 | "node_modules/proxy-addr": {
1315 | "version": "2.0.7",
1316 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
1317 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
1318 | "dependencies": {
1319 | "forwarded": "0.2.0",
1320 | "ipaddr.js": "1.9.1"
1321 | },
1322 | "engines": {
1323 | "node": ">= 0.10"
1324 | }
1325 | },
1326 | "node_modules/punycode": {
1327 | "version": "2.3.1",
1328 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
1329 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
1330 | "engines": {
1331 | "node": ">=6"
1332 | }
1333 | },
1334 | "node_modules/qs": {
1335 | "version": "6.11.0",
1336 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
1337 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
1338 | "dependencies": {
1339 | "side-channel": "^1.0.4"
1340 | },
1341 | "engines": {
1342 | "node": ">=0.6"
1343 | },
1344 | "funding": {
1345 | "url": "https://github.com/sponsors/ljharb"
1346 | }
1347 | },
1348 | "node_modules/range-parser": {
1349 | "version": "1.2.1",
1350 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1351 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
1352 | "engines": {
1353 | "node": ">= 0.6"
1354 | }
1355 | },
1356 | "node_modules/raw-body": {
1357 | "version": "2.5.2",
1358 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
1359 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
1360 | "dependencies": {
1361 | "bytes": "3.1.2",
1362 | "http-errors": "2.0.0",
1363 | "iconv-lite": "0.4.24",
1364 | "unpipe": "1.0.0"
1365 | },
1366 | "engines": {
1367 | "node": ">= 0.8"
1368 | }
1369 | },
1370 | "node_modules/readable-stream": {
1371 | "version": "3.6.2",
1372 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
1373 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
1374 | "dependencies": {
1375 | "inherits": "^2.0.3",
1376 | "string_decoder": "^1.1.1",
1377 | "util-deprecate": "^1.0.1"
1378 | },
1379 | "engines": {
1380 | "node": ">= 6"
1381 | }
1382 | },
1383 | "node_modules/redis": {
1384 | "version": "4.6.14",
1385 | "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.14.tgz",
1386 | "integrity": "sha512-GrNg/e33HtsQwNXL7kJT+iNFPSwE1IPmd7wzV3j4f2z0EYxZfZE7FVTmUysgAtqQQtg5NXF5SNLR9OdO/UHOfw==",
1387 | "dependencies": {
1388 | "@redis/bloom": "1.2.0",
1389 | "@redis/client": "1.5.16",
1390 | "@redis/graph": "1.1.1",
1391 | "@redis/json": "1.0.6",
1392 | "@redis/search": "1.1.6",
1393 | "@redis/time-series": "1.0.5"
1394 | }
1395 | },
1396 | "node_modules/rimraf": {
1397 | "version": "3.0.2",
1398 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
1399 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
1400 | "deprecated": "Rimraf versions prior to v4 are no longer supported",
1401 | "dependencies": {
1402 | "glob": "^7.1.3"
1403 | },
1404 | "bin": {
1405 | "rimraf": "bin.js"
1406 | },
1407 | "funding": {
1408 | "url": "https://github.com/sponsors/isaacs"
1409 | }
1410 | },
1411 | "node_modules/safe-buffer": {
1412 | "version": "5.2.1",
1413 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1414 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1415 | "funding": [
1416 | {
1417 | "type": "github",
1418 | "url": "https://github.com/sponsors/feross"
1419 | },
1420 | {
1421 | "type": "patreon",
1422 | "url": "https://www.patreon.com/feross"
1423 | },
1424 | {
1425 | "type": "consulting",
1426 | "url": "https://feross.org/support"
1427 | }
1428 | ]
1429 | },
1430 | "node_modules/safer-buffer": {
1431 | "version": "2.1.2",
1432 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1433 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1434 | },
1435 | "node_modules/semver": {
1436 | "version": "7.6.3",
1437 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
1438 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
1439 | "bin": {
1440 | "semver": "bin/semver.js"
1441 | },
1442 | "engines": {
1443 | "node": ">=10"
1444 | }
1445 | },
1446 | "node_modules/send": {
1447 | "version": "0.18.0",
1448 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
1449 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
1450 | "dependencies": {
1451 | "debug": "2.6.9",
1452 | "depd": "2.0.0",
1453 | "destroy": "1.2.0",
1454 | "encodeurl": "~1.0.2",
1455 | "escape-html": "~1.0.3",
1456 | "etag": "~1.8.1",
1457 | "fresh": "0.5.2",
1458 | "http-errors": "2.0.0",
1459 | "mime": "1.6.0",
1460 | "ms": "2.1.3",
1461 | "on-finished": "2.4.1",
1462 | "range-parser": "~1.2.1",
1463 | "statuses": "2.0.1"
1464 | },
1465 | "engines": {
1466 | "node": ">= 0.8.0"
1467 | }
1468 | },
1469 | "node_modules/send/node_modules/ms": {
1470 | "version": "2.1.3",
1471 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1472 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1473 | },
1474 | "node_modules/serve-static": {
1475 | "version": "1.15.0",
1476 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
1477 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
1478 | "dependencies": {
1479 | "encodeurl": "~1.0.2",
1480 | "escape-html": "~1.0.3",
1481 | "parseurl": "~1.3.3",
1482 | "send": "0.18.0"
1483 | },
1484 | "engines": {
1485 | "node": ">= 0.8.0"
1486 | }
1487 | },
1488 | "node_modules/set-blocking": {
1489 | "version": "2.0.0",
1490 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
1491 | "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
1492 | },
1493 | "node_modules/set-function-length": {
1494 | "version": "1.2.2",
1495 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
1496 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
1497 | "dependencies": {
1498 | "define-data-property": "^1.1.4",
1499 | "es-errors": "^1.3.0",
1500 | "function-bind": "^1.1.2",
1501 | "get-intrinsic": "^1.2.4",
1502 | "gopd": "^1.0.1",
1503 | "has-property-descriptors": "^1.0.2"
1504 | },
1505 | "engines": {
1506 | "node": ">= 0.4"
1507 | }
1508 | },
1509 | "node_modules/setprototypeof": {
1510 | "version": "1.2.0",
1511 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1512 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
1513 | },
1514 | "node_modules/side-channel": {
1515 | "version": "1.0.6",
1516 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
1517 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
1518 | "dependencies": {
1519 | "call-bind": "^1.0.7",
1520 | "es-errors": "^1.3.0",
1521 | "get-intrinsic": "^1.2.4",
1522 | "object-inspect": "^1.13.1"
1523 | },
1524 | "engines": {
1525 | "node": ">= 0.4"
1526 | },
1527 | "funding": {
1528 | "url": "https://github.com/sponsors/ljharb"
1529 | }
1530 | },
1531 | "node_modules/sift": {
1532 | "version": "17.1.3",
1533 | "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz",
1534 | "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ=="
1535 | },
1536 | "node_modules/signal-exit": {
1537 | "version": "3.0.7",
1538 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
1539 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
1540 | },
1541 | "node_modules/sparse-bitfield": {
1542 | "version": "3.0.3",
1543 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
1544 | "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
1545 | "dependencies": {
1546 | "memory-pager": "^1.0.2"
1547 | }
1548 | },
1549 | "node_modules/statuses": {
1550 | "version": "2.0.1",
1551 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
1552 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
1553 | "engines": {
1554 | "node": ">= 0.8"
1555 | }
1556 | },
1557 | "node_modules/string_decoder": {
1558 | "version": "1.3.0",
1559 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
1560 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
1561 | "dependencies": {
1562 | "safe-buffer": "~5.2.0"
1563 | }
1564 | },
1565 | "node_modules/string-width": {
1566 | "version": "4.2.3",
1567 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1568 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1569 | "dependencies": {
1570 | "emoji-regex": "^8.0.0",
1571 | "is-fullwidth-code-point": "^3.0.0",
1572 | "strip-ansi": "^6.0.1"
1573 | },
1574 | "engines": {
1575 | "node": ">=8"
1576 | }
1577 | },
1578 | "node_modules/strip-ansi": {
1579 | "version": "6.0.1",
1580 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1581 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1582 | "dependencies": {
1583 | "ansi-regex": "^5.0.1"
1584 | },
1585 | "engines": {
1586 | "node": ">=8"
1587 | }
1588 | },
1589 | "node_modules/tar": {
1590 | "version": "6.2.1",
1591 | "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
1592 | "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
1593 | "dependencies": {
1594 | "chownr": "^2.0.0",
1595 | "fs-minipass": "^2.0.0",
1596 | "minipass": "^5.0.0",
1597 | "minizlib": "^2.1.1",
1598 | "mkdirp": "^1.0.3",
1599 | "yallist": "^4.0.0"
1600 | },
1601 | "engines": {
1602 | "node": ">=10"
1603 | }
1604 | },
1605 | "node_modules/toidentifier": {
1606 | "version": "1.0.1",
1607 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1608 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
1609 | "engines": {
1610 | "node": ">=0.6"
1611 | }
1612 | },
1613 | "node_modules/tr46": {
1614 | "version": "4.1.1",
1615 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
1616 | "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
1617 | "dependencies": {
1618 | "punycode": "^2.3.0"
1619 | },
1620 | "engines": {
1621 | "node": ">=14"
1622 | }
1623 | },
1624 | "node_modules/type-is": {
1625 | "version": "1.6.18",
1626 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1627 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1628 | "dependencies": {
1629 | "media-typer": "0.3.0",
1630 | "mime-types": "~2.1.24"
1631 | },
1632 | "engines": {
1633 | "node": ">= 0.6"
1634 | }
1635 | },
1636 | "node_modules/typescript": {
1637 | "version": "5.4.5",
1638 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
1639 | "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
1640 | "dev": true,
1641 | "bin": {
1642 | "tsc": "bin/tsc",
1643 | "tsserver": "bin/tsserver"
1644 | },
1645 | "engines": {
1646 | "node": ">=14.17"
1647 | }
1648 | },
1649 | "node_modules/undici-types": {
1650 | "version": "5.26.5",
1651 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
1652 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
1653 | },
1654 | "node_modules/unpipe": {
1655 | "version": "1.0.0",
1656 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1657 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
1658 | "engines": {
1659 | "node": ">= 0.8"
1660 | }
1661 | },
1662 | "node_modules/util-deprecate": {
1663 | "version": "1.0.2",
1664 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1665 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
1666 | },
1667 | "node_modules/utils-merge": {
1668 | "version": "1.0.1",
1669 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1670 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
1671 | "engines": {
1672 | "node": ">= 0.4.0"
1673 | }
1674 | },
1675 | "node_modules/vary": {
1676 | "version": "1.1.2",
1677 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1678 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
1679 | "engines": {
1680 | "node": ">= 0.8"
1681 | }
1682 | },
1683 | "node_modules/webidl-conversions": {
1684 | "version": "7.0.0",
1685 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
1686 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
1687 | "engines": {
1688 | "node": ">=12"
1689 | }
1690 | },
1691 | "node_modules/whatwg-url": {
1692 | "version": "13.0.0",
1693 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz",
1694 | "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==",
1695 | "dependencies": {
1696 | "tr46": "^4.1.1",
1697 | "webidl-conversions": "^7.0.0"
1698 | },
1699 | "engines": {
1700 | "node": ">=16"
1701 | }
1702 | },
1703 | "node_modules/wide-align": {
1704 | "version": "1.1.5",
1705 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
1706 | "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
1707 | "dependencies": {
1708 | "string-width": "^1.0.2 || 2 || 3 || 4"
1709 | }
1710 | },
1711 | "node_modules/wrappy": {
1712 | "version": "1.0.2",
1713 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1714 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
1715 | },
1716 | "node_modules/ws": {
1717 | "version": "8.18.0",
1718 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
1719 | "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
1720 | "engines": {
1721 | "node": ">=10.0.0"
1722 | },
1723 | "peerDependencies": {
1724 | "bufferutil": "^4.0.1",
1725 | "utf-8-validate": ">=5.0.2"
1726 | },
1727 | "peerDependenciesMeta": {
1728 | "bufferutil": {
1729 | "optional": true
1730 | },
1731 | "utf-8-validate": {
1732 | "optional": true
1733 | }
1734 | }
1735 | },
1736 | "node_modules/yallist": {
1737 | "version": "4.0.0",
1738 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
1739 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
1740 | }
1741 | }
1742 | }
1743 |
--------------------------------------------------------------------------------