├── server ├── .env.sample ├── routes │ └── route.js ├── .gitignore ├── package.json ├── model │ └── Todo.js ├── index.js ├── Readme.md ├── Database │ └── DB.js ├── controller │ └── Controller.js └── package-lock.json ├── Template.png ├── client ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── manifest.json │ └── index.html ├── src │ ├── Components │ │ ├── Header.jsx │ │ ├── Tabs.jsx │ │ ├── ToDoForm.jsx │ │ ├── Todo.jsx │ │ └── Todos.jsx │ ├── Redux │ │ ├── reducers │ │ │ ├── tabReducer.js │ │ │ └── todosReducer.js │ │ ├── actions │ │ │ ├── type.js │ │ │ └── index.js │ │ └── Store.js │ ├── App.js │ ├── index.css │ ├── reportWebVitals.js │ ├── index.js │ └── App.css ├── .gitignore ├── package.json └── README.md ├── LICENSE.md └── Readme.md /server/.env.sample: -------------------------------------------------------------------------------- 1 | DB_URL = Paste ur DB url here -------------------------------------------------------------------------------- /Template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/himanshu1221/To-Do-Web-App/HEAD/Template.png -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/himanshu1221/To-Do-Web-App/HEAD/client/public/favicon.ico -------------------------------------------------------------------------------- /client/src/Components/Header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const Header = () => { 4 | return ( 5 | <> 6 |
7 |

To Do List

8 |
9 | 10 | ) 11 | } 12 | 13 | export default Header -------------------------------------------------------------------------------- /client/src/Redux/reducers/tabReducer.js: -------------------------------------------------------------------------------- 1 | import * as actionTypes from "../actions/type" 2 | 3 | 4 | export const tabReducer = (state = actionTypes.ALL_TODO,action) => { 5 | switch(action.type){ 6 | case actionTypes.TOGGLE_TAB: 7 | return action.selected 8 | default: 9 | return state 10 | } 11 | } -------------------------------------------------------------------------------- /client/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import Header from './Components/Header'; 3 | import ToDoForm from './Components/ToDoForm'; 4 | import Todos from './Components/Todos'; 5 | 6 | function App() { 7 | return ( 8 | <> 9 |
10 | 11 | 12 | 13 | ); 14 | } 15 | 16 | export default App; 17 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /server/routes/route.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { addTodo,getAllTodos,toggleTodoDone,updateTodo,deleteTodo } from "../controller/Controller.js"; 3 | const Routes = express.Router(); 4 | 5 | Routes.post('/todos', addTodo) 6 | Routes.get('/todos',getAllTodos ) 7 | Routes.get('/todos/:id',toggleTodoDone) 8 | Routes.put('/todos/:id',updateTodo) 9 | Routes.delete('/todos/:id',deleteTodo) 10 | 11 | export default Routes; -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | .env 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /client/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /client/src/Redux/actions/type.js: -------------------------------------------------------------------------------- 1 | export const ADDNEW_TODO = "ADDNEW_TODO" 2 | export const GETALL_TODO = "GETALL_TODO" 3 | export const TOGGLE_TODO = "TOGGLE_TODO" 4 | export const UPDATE_TODO = "UPDATE_TODO" 5 | export const DELETE_TODO = "DELETE_TODO" 6 | export const TOGGLE_TAB = "TOGGLE_TAB" 7 | export const ALL_TODO = "All Todo" 8 | export const ACTIVE_TODO = "Active Todo" 9 | export const DONE_TODO = "Done Todo" 10 | export const TABS = [ALL_TODO,ACTIVE_TODO,DONE_TODO] -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "Server for To Do app", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "start": "nodemon index.js" 9 | }, 10 | "author": "Himanshu Chhatwal", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.20.2", 14 | "cors": "^2.8.5", 15 | "dotenv": "^16.0.3", 16 | "express": "^4.18.2", 17 | "mongoose": "^7.0.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/model/Todo.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | // here we will validate the data fro frontend 4 | 5 | const TodoSchema = new mongoose.Schema({ 6 | data : { 7 | type:String, 8 | required : true 9 | }, 10 | done:{ 11 | type:Boolean, 12 | default: false 13 | }, 14 | createdAt:{ 15 | type : Date, 16 | default : Date.now 17 | } 18 | }) 19 | 20 | const todo = mongoose.model('todo',TodoSchema) 21 | 22 | export default todo; -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import connection from "./Database/DB.js"; 3 | import cors from "cors" 4 | import Routes from "./routes/route.js"; 5 | import bodyParser from "body-parser"; 6 | 7 | const app = express(); 8 | 9 | app.use(cors()) 10 | app.use(bodyParser.json({extended:true})) 11 | app.use(bodyParser.urlencoded({extended:true})) 12 | app.use('/',Routes) 13 | const PORT = 8000; 14 | 15 | connection(); 16 | 17 | app.listen(PORT,()=> console.log(`Server Initialised on port ${PORT}`)) -------------------------------------------------------------------------------- /client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import store from './Redux/Store'; 7 | import { Provider } from 'react-redux'; 8 | 9 | const root = ReactDOM.createRoot(document.getElementById('root')); 10 | root.render( 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /server/Readme.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | - This is the backend folder of the project 4 | 5 | ## Available Scripts 6 | 7 | - In the project directory, you can run: 8 | 9 | ### `npm Install` 10 | 11 | - To install all the dependecies 12 | 13 | ### `.env` 14 | 15 | - Create a `.env` file and copy the configuration from `.env.sample` to `.env` and replace the configs by your configs 16 | 17 | ### `npm start` 18 | 19 | - Runs the app in the development mode.\ 20 | - Runs the server on [http://localhost:8000](http://localhost:8000) -------------------------------------------------------------------------------- /client/src/Components/Tabs.jsx: -------------------------------------------------------------------------------- 1 | import { useDispatch } from "react-redux" 2 | import { TABS } from "../Redux/actions/type" 3 | import { toggleTab } from "../Redux/actions"; 4 | 5 | 6 | const Tabs = ({ currentTab }) => { 7 | const dispatch = useDispatch(); 8 | return( 9 | TABS.map(tab=>( 10 | 15 | )) 16 | ) 17 | } 18 | 19 | export default Tabs -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /server/Database/DB.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose" 2 | import dotenv from "dotenv" 3 | 4 | dotenv.config(); 5 | 6 | // create a .env file with the help of .env.sample 7 | 8 | const DB_URL = process.env.DB_URL 9 | 10 | const connection = () => { 11 | 12 | const MONGODB_URI = `${DB_URL}`; 13 | 14 | // this is used to connect mongodb // old parser will be depriciated we will soon use new parser 15 | 16 | mongoose.connect(MONGODB_URI , { useNewUrlParser : true }); 17 | 18 | mongoose.connection.on('connected',()=>{ 19 | console.log("database connected succefully") 20 | }) 21 | 22 | mongoose.connection.on("disconnected",()=>{ 23 | console.log("database disconnected") 24 | }) 25 | 26 | mongoose.connection.on('error',(error)=>{ 27 | console.log("error while connecting with database",error.message) 28 | }) 29 | } 30 | 31 | export default connection; -------------------------------------------------------------------------------- /client/src/Redux/Store.js: -------------------------------------------------------------------------------- 1 | import { createStore,combineReducers,applyMiddleware } from "redux" 2 | import thunk from "redux-thunk"; 3 | import { composeWithDevTools } from "redux-devtools-extension"; 4 | import todosReducer from "./reducers/todosReducer"; 5 | import { tabReducer } from "./reducers/tabReducer"; 6 | 7 | const reducer = combineReducers({ 8 | todos: todosReducer, 9 | currentTab:tabReducer 10 | 11 | }); 12 | 13 | const middleware = [thunk]; 14 | 15 | const store = createStore( 16 | 17 | //we can perform action items with the help of reducers we use combine reducer to combine multiple task CRUD 18 | 19 | //with the help of redux devtools extension we can connect with dev tools extension in the browser to store the data 20 | 21 | //we are using thunk as a middle ware 22 | 23 | reducer, 24 | composeWithDevTools(applyMiddleware(...middleware)) 25 | ) 26 | 27 | export default store; -------------------------------------------------------------------------------- /client/src/Redux/reducers/todosReducer.js: -------------------------------------------------------------------------------- 1 | import * as actionTypes from '../actions/type' 2 | 3 | 4 | const todosReducer = (state = [] , action) => { 5 | 6 | switch(action.type){ 7 | case actionTypes.ADDNEW_TODO: 8 | return[action.payload,...state] 9 | 10 | case actionTypes.GETALL_TODO: 11 | return action.payload 12 | 13 | case actionTypes.TOGGLE_TODO: 14 | return state.map(todo =>( 15 | todo._id === action.payload._id ? {...todo,done:!todo.done} : todo 16 | )) 17 | case actionTypes.UPDATE_TODO: 18 | return state.map(todo =>( 19 | todo._id === action.payload._id ? {...todo,data:action.payload.data} : todo 20 | )) 21 | 22 | case actionTypes.DELETE_TODO: 23 | return state.filter(todo => todo._id !== action.payload._id) 24 | 25 | default: 26 | return state; 27 | } 28 | 29 | } 30 | 31 | export default todosReducer; -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | To-Do WebApp 16 | 17 | 18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /client/src/Components/ToDoForm.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react" 2 | import { addNewTodo } from "../Redux/actions" 3 | import { useDispatch } from "react-redux" 4 | 5 | // Redux is a databse for frontend 6 | 7 | const ToDoForm = () => { 8 | 9 | const dispatch = useDispatch(); 10 | 11 | // we are using state to store the value of input field 12 | 13 | const[text,setText] = useState("") 14 | 15 | // we use onformsubmit to handle page refresh 16 | 17 | const onFormSubmit = (e) =>{ 18 | e.preventDefault(); 19 | dispatch(addNewTodo(text)) 20 | setText("") 21 | } 22 | 23 | // we used onInputChange to find out the value written inn input field 24 | 25 | const onInputChange = (e) => { 26 | // console.log(e.target.value) 27 | setText(e.target.value) 28 | } 29 | 30 | 31 | return( 32 |
33 | 34 |
35 | ) 36 | } 37 | 38 | export default ToDoForm; -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Himanshu Chhatwal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "axios": "^1.3.4", 10 | "font-awesome": "^4.7.0", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-redux": "^8.0.5", 14 | "react-scripts": "5.0.1", 15 | "redux": "^4.2.1", 16 | "redux-devtools-extension": "^2.13.9", 17 | "redux-thunk": "^2.4.2", 18 | "web-vitals": "^2.1.4" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "test": "react-scripts test", 24 | "eject": "react-scripts eject" 25 | }, 26 | "eslintConfig": { 27 | "extends": [ 28 | "react-app", 29 | "react-app/jest" 30 | ] 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /client/src/App.css: -------------------------------------------------------------------------------- 1 | body{ 2 | width: 50%; 3 | margin: 0 auto; 4 | } 5 | 6 | header{ 7 | text-align: center; 8 | } 9 | 10 | header h1 { 11 | font-size: 100px; 12 | color: #2c3e50; 13 | font-weight: 200; 14 | } 15 | 16 | input{ 17 | font-size: 20px; 18 | color: #2c3e50; 19 | width: 100%; 20 | border: none; 21 | outline: none; 22 | border-bottom: 1px solid #2c3e50; 23 | padding: 5px; 24 | } 25 | 26 | .task{ 27 | background-color: #34495e; 28 | padding: 20px; 29 | margin: 5px; 30 | list-style: none; 31 | border-radius: 5px; 32 | cursor: pointer; 33 | 34 | } 35 | 36 | .task span{ 37 | color: white; 38 | } 39 | 40 | .icon{ 41 | float: right; 42 | margin-right: 20px; 43 | } 44 | 45 | article{ 46 | display: grid; 47 | } 48 | 49 | .edit-todo{ 50 | width: 80%; 51 | font-size: 16px; 52 | color: #fff; 53 | background: transparent; 54 | border: none; 55 | border-bottom: 1px solid #fff; 56 | } 57 | 58 | .button{ 59 | margin: 0px 10px; 60 | padding: 10px; 61 | font-size: 14px; 62 | color: #6c6777; 63 | background: #fff; 64 | border: none; 65 | cursor: pointer; 66 | width: 100px; 67 | border-radius: 5px; 68 | margin-top: 15px; 69 | } 70 | 71 | .button.selected{ 72 | color: #fff; 73 | background-color: #6c6777; 74 | } 75 | 76 | .button.clear{ 77 | float: right; 78 | color: white; 79 | background-color: red; 80 | width: 170px; 81 | } -------------------------------------------------------------------------------- /client/src/Components/Todo.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { toggleTodo,updateTodo,deleteTodo } from "../Redux/actions" 3 | import { useDispatch } from "react-redux" 4 | 5 | const Todo = ({ todo }) => { 6 | 7 | const[editing,setEditing] = useState(false); 8 | const [text,setText] = useState(todo.data) 9 | const dispatch = useDispatch(); 10 | const onFormSubmit = (e) => { 11 | e.preventDefault() 12 | setEditing(prevstate => !prevstate) 13 | dispatch(updateTodo(todo._id,text)) 14 | } 15 | 16 | return( 17 |
18 |
  • dispatch(toggleTodo(todo._id))} 20 | style={{ 21 | textDecoration: todo.done ? 'line-through' : "", 22 | color: todo.done ? '#bdc3c7' : '#34495e' 23 | }} 24 | > 25 | {todo.data} 26 |
    30 | setText(e.target.value)} 34 | /> 35 |
    36 | dispatch(deleteTodo(todo._id))}> 37 | 38 | 39 | setEditing(prevstate => !prevstate)}> 40 | 41 | 42 |
  • 43 |
    44 | ) 45 | } 46 | 47 | export default Todo; -------------------------------------------------------------------------------- /server/controller/Controller.js: -------------------------------------------------------------------------------- 1 | import Todo from "../model/Todo.js" 2 | 3 | 4 | export const addTodo = async (request,response) => { 5 | try{ 6 | const newTodo = await Todo.create({ 7 | data:request.body.data, 8 | createdAt : Date.now() 9 | }) 10 | await newTodo.save() 11 | 12 | return response.status(200).json(newTodo) 13 | }catch(error){ 14 | return response.status(500).json(error.message) 15 | } 16 | } 17 | 18 | export const getAllTodos = async (request,response) => { 19 | try{ 20 | const todos = await Todo.find({}).sort({ 'createdAt':-1 }) 21 | return response.status(200).json(todos) 22 | }catch(error){ 23 | return response.status(500).json(error.message) 24 | } 25 | } 26 | 27 | export const toggleTodoDone = async (request,response) => { 28 | try{ 29 | const todoRef = await Todo.findById(request.params.id) 30 | const todo = await Todo.findOneAndUpdate( 31 | { _id:request.params.id }, 32 | { done : !todoRef.done } 33 | ) 34 | await todo.save() 35 | return response.status(200).json(todo) 36 | }catch(error){ 37 | return response.status(500).json(error.message) 38 | } 39 | } 40 | 41 | export const updateTodo = async (request,response) => { 42 | try{ 43 | await Todo.findOneAndUpdate( 44 | {_id:request.params.id}, 45 | {data:request.body.data} 46 | ) 47 | 48 | const todo = await Todo.findById(request.params.id) 49 | 50 | return response.status(200).json(todo) 51 | }catch(error){ 52 | return response.status(500).json(error.message) 53 | } 54 | } 55 | 56 | export const deleteTodo = async (request,response) => { 57 | try{ 58 | const todo = await Todo.findByIdAndDelete(request.params.id) 59 | return response.status(200).json(todo) 60 | }catch(error){ 61 | return response.status(500).json(error.message) 62 | } 63 | } -------------------------------------------------------------------------------- /client/src/Components/Todos.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react" 2 | import { deleteTodo, getAllTodos } from "../Redux/actions/index" 3 | import { useDispatch,useSelector } from "react-redux" 4 | import Todo from "./Todo"; 5 | import Tabs from "./Tabs"; 6 | import { ALL_TODO,DONE_TODO,ACTIVE_TODO } from "../Redux/actions/type"; 7 | export const Todos = () => { 8 | 9 | const dispatch = useDispatch(); 10 | 11 | 12 | const todos = useSelector(state => state.todos) 13 | const currentTab = useSelector(state => state.currentTab) 14 | 15 | useEffect(()=>{ 16 | dispatch(getAllTodos()) 17 | },[]) 18 | 19 | const getTodos = () => { 20 | if(currentTab === ALL_TODO ){ 21 | return todos 22 | }else if (currentTab === ACTIVE_TODO){ 23 | return todos.filter(todos => !todos.done) 24 | }else if(currentTab === DONE_TODO){ 25 | return todos.filter(todos => todos.done) 26 | } 27 | } 28 | 29 | const removeDoneTodos = () => { 30 | todos.forEach(({done,_id})=>{ 31 | if (done){ 32 | dispatch(deleteTodo(_id)) 33 | } 34 | 35 | 36 | }) 37 | } 38 | 39 | return( 40 |
    41 |
    42 | 43 | { 44 | todos.some(todo => todo.done) ?( 45 | 49 | ) : null 50 | } 51 |
    52 |
      53 | { 54 | getTodos().map(todo => ( 55 | 59 | )) 60 | } 61 |
    62 |
    63 | ) 64 | } 65 | 66 | export default Todos -------------------------------------------------------------------------------- /client/src/Redux/actions/index.js: -------------------------------------------------------------------------------- 1 | import axios from "axios" 2 | import { ADDNEW_TODO, GETALL_TODO,TOGGLE_TODO,UPDATE_TODO,DELETE_TODO,TOGGLE_TAB } from "./type"; 3 | const API_URL = "http://localhost:8000"; 4 | 5 | export const addNewTodo = (data) => async(dispatch) =>{ 6 | 7 | // Post is used to post a todo 8 | 9 | try{ 10 | 11 | const res = await axios.post(`${API_URL}/todos`,{ data }) 12 | 13 | dispatch( 14 | { 15 | type : ADDNEW_TODO, 16 | payload : res.data 17 | } 18 | ) 19 | }catch(error){ 20 | console.log("error in adding new ToDo",error) 21 | } 22 | } 23 | 24 | export const getAllTodos = () => async (dispatch)=>{ 25 | try{ 26 | 27 | const res = await axios.get(`${API_URL}/todos`) 28 | 29 | dispatch( 30 | { 31 | type : GETALL_TODO, 32 | payload : res.data 33 | } 34 | ) 35 | }catch(error){ 36 | console.log("error while calling getalltodo api",error) 37 | } 38 | } 39 | 40 | 41 | export const toggleTodo = (id) => async (dispatch)=>{ 42 | try{ 43 | 44 | const res = await axios.get(`${API_URL}/todos/${id}`) 45 | 46 | dispatch( 47 | { 48 | type : TOGGLE_TODO, 49 | payload : res.data 50 | } 51 | ) 52 | }catch(error){ 53 | console.log("error while calling getalltodo api",error) 54 | } 55 | } 56 | 57 | export const updateTodo = (id,data) => async (dispatch)=>{ 58 | try{ 59 | 60 | const res = await axios.put(`${API_URL}/todos/${id}`,{data}) 61 | 62 | dispatch( 63 | { 64 | type : UPDATE_TODO, 65 | payload : res.data 66 | } 67 | ) 68 | }catch(error){ 69 | console.log("error while calling Updatealltodo api",error) 70 | } 71 | } 72 | 73 | export const deleteTodo = (id) => async (dispatch)=>{ 74 | try{ 75 | 76 | const res = await axios.delete(`${API_URL}/todos/${id}`) 77 | 78 | dispatch( 79 | { 80 | type : DELETE_TODO, 81 | payload : res.data 82 | } 83 | ) 84 | }catch(error){ 85 | console.log("error while calling deletealltodo api",error) 86 | } 87 | } 88 | 89 | export const toggleTab = (tab) => async (dispatch) => { 90 | dispatch( 91 | { 92 | type:TOGGLE_TAB, 93 | selected:tab 94 | } 95 | ) 96 | } -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # To-Do-Web-App 2 | 3 | Template 4 | 5 | - This is a Todo application built with the MERN stack (MongoDB, Express, React, and Node.js) and Redux. The application allows users to create, edit, and delete todos. Users can also mark todos as completed or not completed. 6 | 7 | ## Installation 8 | 9 | To install the Todo app, follow these steps: 10 | 11 | #### 1. Clone the repository: 12 | 13 | `git clone https://github.com/{your-username}/To-Do-Web-App.git` 14 | 15 | 16 | #### 2. Navigate to the root directory of the project and install the dependencies: 17 | 18 | - `cd Client` for Front-end 19 | - `cd server` for Back-end 20 | - `npm install` to install all the dependecies 21 | 22 | #### 3. Create a `.env` file and copy the configuration from `.env.sample` to `.env` and replace the configs by your configs 23 | 24 | #### 4. Start the application: 25 | 26 | Step 1 : 27 | - `npm start` in the server folder 28 | start the server and make sure you get logs in console that are 29 | - `Server Initialised on port 8000` 30 | - `database connected succefully` 31 | 32 | Step 2 : 33 | - `npm start` in the client folder 34 | - Your development build will start 35 | 36 | #### 5. Open your web browser and go to `http://localhost:3000` to view the application. 37 | 38 | 39 | ## Usage 40 | 41 | ### Adding a Todo 42 | 43 | To add a new Todo, click the "Add Todo" button in the header. Type in the name of the Todo in the input field and press "Enter" or click the "Add" button. The new Todo will be added to the list. 44 | 45 | ### Editing a Todo 46 | 47 | To edit a Todo, click the "Pen" button next to the Todo you want to edit. The Todo will be displayed in an input field. Make your changes and press "Enter". 48 | 49 | ### Deleting a Todo 50 | 51 | To delete a Todo, click the "Trash" button next to the Todo you want to delete. The Todo will be removed from the list. 52 | 53 | ### Completing a Todo 54 | 55 | To mark a Todo as completed, click the on Todo. The Todo will be crossed out to indicate that it has been completed. 56 | 57 | ### Filtering Todos 58 | 59 | To filter the list of Todos, click the "All todo", "Active todo", or "Done todo" buttons in the header. The list will show only the Todos that match the selected filter. 60 | 61 | ## Dependencies 62 | 63 | The Todo app uses the following dependencies: 64 | 65 | - `axios`: for making HTTP requests to the backend API 66 | - `react`: for building the user interface 67 | - `react-dom`: for rendering the user interface 68 | - `react-redux`: for managing application state with Redux 69 | - `react-router-dom`: for client-side routing 70 | - `redux`: for managing application state 71 | - `redux-thunk`: for handling asynchronous actions in Redux 72 | - `redux-devtools-extensions`: for effective use of redux 73 | - `font-awesome`: for fonts that are used in the web-app 74 | - `express`: for creating routes 75 | - `dotenv`: to use the .env file in react 76 | - `mongoose`: to create schemas and connect it to Database 77 | 78 | ## License 79 | 80 | The Todo app is licensed under the MIT License. See the [LICENSE](https://github.com/himanshu1221/To-Do-Web-App/blob/master/LICENSE.md) file for more information. 81 | 82 | ## Resources 83 | - [Axios](https://axios-http.com/docs/intro) 84 | - [React](https://create-react-app.dev/) 85 | - [React Dom](https://legacy.reactjs.org/docs/react-dom.html) 86 | - [React Redux](https://react-redux.js.org/introduction/getting-started) 87 | - [React router dom](https://reactrouter.com/en/main/start/overview) 88 | - [Redux](https://redux.js.org/introduction/getting-started) 89 | - [Redux Thunk](https://redux.js.org/usage/writing-logic-thunks) 90 | - [Redux devtools extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en) 91 | - [font-awesome](https://fontawesome.com/docs) 92 | - [express](https://expressjs.com/en/guide/routing.html) 93 | - [dotenv](https://www.npmjs.com/package/dotenv) 94 | - [mongoose](https://mongoosejs.com/docs/guide.html) 95 | - [Todo web app part 1](https://youtu.be/0UJ8TPg1yiE) 96 | - [Todo web app part 2](https://youtu.be/CG_nh3vJ1Yo) 97 | -------------------------------------------------------------------------------- /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 | "body-parser": "^1.20.2", 13 | "cors": "^2.8.5", 14 | "dotenv": "^16.0.3", 15 | "express": "^4.18.2", 16 | "mongoose": "^7.0.3" 17 | } 18 | }, 19 | "node_modules/@types/node": { 20 | "version": "18.15.10", 21 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz", 22 | "integrity": "sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==" 23 | }, 24 | "node_modules/@types/webidl-conversions": { 25 | "version": "7.0.0", 26 | "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 27 | "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" 28 | }, 29 | "node_modules/@types/whatwg-url": { 30 | "version": "8.2.2", 31 | "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", 32 | "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", 33 | "dependencies": { 34 | "@types/node": "*", 35 | "@types/webidl-conversions": "*" 36 | } 37 | }, 38 | "node_modules/accepts": { 39 | "version": "1.3.8", 40 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 41 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 42 | "dependencies": { 43 | "mime-types": "~2.1.34", 44 | "negotiator": "0.6.3" 45 | }, 46 | "engines": { 47 | "node": ">= 0.6" 48 | } 49 | }, 50 | "node_modules/array-flatten": { 51 | "version": "1.1.1", 52 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 53 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 54 | }, 55 | "node_modules/body-parser": { 56 | "version": "1.20.2", 57 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", 58 | "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", 59 | "dependencies": { 60 | "bytes": "3.1.2", 61 | "content-type": "~1.0.5", 62 | "debug": "2.6.9", 63 | "depd": "2.0.0", 64 | "destroy": "1.2.0", 65 | "http-errors": "2.0.0", 66 | "iconv-lite": "0.4.24", 67 | "on-finished": "2.4.1", 68 | "qs": "6.11.0", 69 | "raw-body": "2.5.2", 70 | "type-is": "~1.6.18", 71 | "unpipe": "1.0.0" 72 | }, 73 | "engines": { 74 | "node": ">= 0.8", 75 | "npm": "1.2.8000 || >= 1.4.16" 76 | } 77 | }, 78 | "node_modules/bson": { 79 | "version": "5.1.0", 80 | "resolved": "https://registry.npmjs.org/bson/-/bson-5.1.0.tgz", 81 | "integrity": "sha512-FEecNHkhYRBe7X9KDkdG12xNuz5VHGeH6mCE0B5sBmYtiR/Ux/9vUH/v4NUoBCDr6NuEhvahjoLiiRogptVW0A==", 82 | "engines": { 83 | "node": ">=14.20.1" 84 | } 85 | }, 86 | "node_modules/bytes": { 87 | "version": "3.1.2", 88 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 89 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 90 | "engines": { 91 | "node": ">= 0.8" 92 | } 93 | }, 94 | "node_modules/call-bind": { 95 | "version": "1.0.2", 96 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 97 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 98 | "dependencies": { 99 | "function-bind": "^1.1.1", 100 | "get-intrinsic": "^1.0.2" 101 | }, 102 | "funding": { 103 | "url": "https://github.com/sponsors/ljharb" 104 | } 105 | }, 106 | "node_modules/content-disposition": { 107 | "version": "0.5.4", 108 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 109 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 110 | "dependencies": { 111 | "safe-buffer": "5.2.1" 112 | }, 113 | "engines": { 114 | "node": ">= 0.6" 115 | } 116 | }, 117 | "node_modules/content-type": { 118 | "version": "1.0.5", 119 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 120 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 121 | "engines": { 122 | "node": ">= 0.6" 123 | } 124 | }, 125 | "node_modules/cookie": { 126 | "version": "0.5.0", 127 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 128 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 129 | "engines": { 130 | "node": ">= 0.6" 131 | } 132 | }, 133 | "node_modules/cookie-signature": { 134 | "version": "1.0.6", 135 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 136 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 137 | }, 138 | "node_modules/cors": { 139 | "version": "2.8.5", 140 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 141 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 142 | "dependencies": { 143 | "object-assign": "^4", 144 | "vary": "^1" 145 | }, 146 | "engines": { 147 | "node": ">= 0.10" 148 | } 149 | }, 150 | "node_modules/debug": { 151 | "version": "2.6.9", 152 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 153 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 154 | "dependencies": { 155 | "ms": "2.0.0" 156 | } 157 | }, 158 | "node_modules/depd": { 159 | "version": "2.0.0", 160 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 161 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 162 | "engines": { 163 | "node": ">= 0.8" 164 | } 165 | }, 166 | "node_modules/destroy": { 167 | "version": "1.2.0", 168 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 169 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 170 | "engines": { 171 | "node": ">= 0.8", 172 | "npm": "1.2.8000 || >= 1.4.16" 173 | } 174 | }, 175 | "node_modules/dotenv": { 176 | "version": "16.0.3", 177 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", 178 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", 179 | "engines": { 180 | "node": ">=12" 181 | } 182 | }, 183 | "node_modules/ee-first": { 184 | "version": "1.1.1", 185 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 186 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 187 | }, 188 | "node_modules/encodeurl": { 189 | "version": "1.0.2", 190 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 191 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 192 | "engines": { 193 | "node": ">= 0.8" 194 | } 195 | }, 196 | "node_modules/escape-html": { 197 | "version": "1.0.3", 198 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 199 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 200 | }, 201 | "node_modules/etag": { 202 | "version": "1.8.1", 203 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 204 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 205 | "engines": { 206 | "node": ">= 0.6" 207 | } 208 | }, 209 | "node_modules/express": { 210 | "version": "4.18.2", 211 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 212 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 213 | "dependencies": { 214 | "accepts": "~1.3.8", 215 | "array-flatten": "1.1.1", 216 | "body-parser": "1.20.1", 217 | "content-disposition": "0.5.4", 218 | "content-type": "~1.0.4", 219 | "cookie": "0.5.0", 220 | "cookie-signature": "1.0.6", 221 | "debug": "2.6.9", 222 | "depd": "2.0.0", 223 | "encodeurl": "~1.0.2", 224 | "escape-html": "~1.0.3", 225 | "etag": "~1.8.1", 226 | "finalhandler": "1.2.0", 227 | "fresh": "0.5.2", 228 | "http-errors": "2.0.0", 229 | "merge-descriptors": "1.0.1", 230 | "methods": "~1.1.2", 231 | "on-finished": "2.4.1", 232 | "parseurl": "~1.3.3", 233 | "path-to-regexp": "0.1.7", 234 | "proxy-addr": "~2.0.7", 235 | "qs": "6.11.0", 236 | "range-parser": "~1.2.1", 237 | "safe-buffer": "5.2.1", 238 | "send": "0.18.0", 239 | "serve-static": "1.15.0", 240 | "setprototypeof": "1.2.0", 241 | "statuses": "2.0.1", 242 | "type-is": "~1.6.18", 243 | "utils-merge": "1.0.1", 244 | "vary": "~1.1.2" 245 | }, 246 | "engines": { 247 | "node": ">= 0.10.0" 248 | } 249 | }, 250 | "node_modules/express/node_modules/body-parser": { 251 | "version": "1.20.1", 252 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 253 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 254 | "dependencies": { 255 | "bytes": "3.1.2", 256 | "content-type": "~1.0.4", 257 | "debug": "2.6.9", 258 | "depd": "2.0.0", 259 | "destroy": "1.2.0", 260 | "http-errors": "2.0.0", 261 | "iconv-lite": "0.4.24", 262 | "on-finished": "2.4.1", 263 | "qs": "6.11.0", 264 | "raw-body": "2.5.1", 265 | "type-is": "~1.6.18", 266 | "unpipe": "1.0.0" 267 | }, 268 | "engines": { 269 | "node": ">= 0.8", 270 | "npm": "1.2.8000 || >= 1.4.16" 271 | } 272 | }, 273 | "node_modules/express/node_modules/raw-body": { 274 | "version": "2.5.1", 275 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 276 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 277 | "dependencies": { 278 | "bytes": "3.1.2", 279 | "http-errors": "2.0.0", 280 | "iconv-lite": "0.4.24", 281 | "unpipe": "1.0.0" 282 | }, 283 | "engines": { 284 | "node": ">= 0.8" 285 | } 286 | }, 287 | "node_modules/finalhandler": { 288 | "version": "1.2.0", 289 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 290 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 291 | "dependencies": { 292 | "debug": "2.6.9", 293 | "encodeurl": "~1.0.2", 294 | "escape-html": "~1.0.3", 295 | "on-finished": "2.4.1", 296 | "parseurl": "~1.3.3", 297 | "statuses": "2.0.1", 298 | "unpipe": "~1.0.0" 299 | }, 300 | "engines": { 301 | "node": ">= 0.8" 302 | } 303 | }, 304 | "node_modules/forwarded": { 305 | "version": "0.2.0", 306 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 307 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 308 | "engines": { 309 | "node": ">= 0.6" 310 | } 311 | }, 312 | "node_modules/fresh": { 313 | "version": "0.5.2", 314 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 315 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 316 | "engines": { 317 | "node": ">= 0.6" 318 | } 319 | }, 320 | "node_modules/function-bind": { 321 | "version": "1.1.1", 322 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 323 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 324 | }, 325 | "node_modules/get-intrinsic": { 326 | "version": "1.2.0", 327 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 328 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 329 | "dependencies": { 330 | "function-bind": "^1.1.1", 331 | "has": "^1.0.3", 332 | "has-symbols": "^1.0.3" 333 | }, 334 | "funding": { 335 | "url": "https://github.com/sponsors/ljharb" 336 | } 337 | }, 338 | "node_modules/has": { 339 | "version": "1.0.3", 340 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 341 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 342 | "dependencies": { 343 | "function-bind": "^1.1.1" 344 | }, 345 | "engines": { 346 | "node": ">= 0.4.0" 347 | } 348 | }, 349 | "node_modules/has-symbols": { 350 | "version": "1.0.3", 351 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 352 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 353 | "engines": { 354 | "node": ">= 0.4" 355 | }, 356 | "funding": { 357 | "url": "https://github.com/sponsors/ljharb" 358 | } 359 | }, 360 | "node_modules/http-errors": { 361 | "version": "2.0.0", 362 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 363 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 364 | "dependencies": { 365 | "depd": "2.0.0", 366 | "inherits": "2.0.4", 367 | "setprototypeof": "1.2.0", 368 | "statuses": "2.0.1", 369 | "toidentifier": "1.0.1" 370 | }, 371 | "engines": { 372 | "node": ">= 0.8" 373 | } 374 | }, 375 | "node_modules/iconv-lite": { 376 | "version": "0.4.24", 377 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 378 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 379 | "dependencies": { 380 | "safer-buffer": ">= 2.1.2 < 3" 381 | }, 382 | "engines": { 383 | "node": ">=0.10.0" 384 | } 385 | }, 386 | "node_modules/inherits": { 387 | "version": "2.0.4", 388 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 389 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 390 | }, 391 | "node_modules/ip": { 392 | "version": "2.0.0", 393 | "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", 394 | "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" 395 | }, 396 | "node_modules/ipaddr.js": { 397 | "version": "1.9.1", 398 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 399 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 400 | "engines": { 401 | "node": ">= 0.10" 402 | } 403 | }, 404 | "node_modules/kareem": { 405 | "version": "2.5.1", 406 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", 407 | "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", 408 | "engines": { 409 | "node": ">=12.0.0" 410 | } 411 | }, 412 | "node_modules/media-typer": { 413 | "version": "0.3.0", 414 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 415 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 416 | "engines": { 417 | "node": ">= 0.6" 418 | } 419 | }, 420 | "node_modules/memory-pager": { 421 | "version": "1.5.0", 422 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 423 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 424 | "optional": true 425 | }, 426 | "node_modules/merge-descriptors": { 427 | "version": "1.0.1", 428 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 429 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 430 | }, 431 | "node_modules/methods": { 432 | "version": "1.1.2", 433 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 434 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 435 | "engines": { 436 | "node": ">= 0.6" 437 | } 438 | }, 439 | "node_modules/mime": { 440 | "version": "1.6.0", 441 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 442 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 443 | "bin": { 444 | "mime": "cli.js" 445 | }, 446 | "engines": { 447 | "node": ">=4" 448 | } 449 | }, 450 | "node_modules/mime-db": { 451 | "version": "1.52.0", 452 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 453 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 454 | "engines": { 455 | "node": ">= 0.6" 456 | } 457 | }, 458 | "node_modules/mime-types": { 459 | "version": "2.1.35", 460 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 461 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 462 | "dependencies": { 463 | "mime-db": "1.52.0" 464 | }, 465 | "engines": { 466 | "node": ">= 0.6" 467 | } 468 | }, 469 | "node_modules/mongodb": { 470 | "version": "5.1.0", 471 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.1.0.tgz", 472 | "integrity": "sha512-qgKb7y+EI90y4weY3z5+lIgm8wmexbonz0GalHkSElQXVKtRuwqXuhXKccyvIjXCJVy9qPV82zsinY0W1FBnJw==", 473 | "dependencies": { 474 | "bson": "^5.0.1", 475 | "mongodb-connection-string-url": "^2.6.0", 476 | "socks": "^2.7.1" 477 | }, 478 | "engines": { 479 | "node": ">=14.20.1" 480 | }, 481 | "optionalDependencies": { 482 | "saslprep": "^1.0.3" 483 | }, 484 | "peerDependencies": { 485 | "@aws-sdk/credential-providers": "^3.201.0", 486 | "mongodb-client-encryption": "^2.3.0", 487 | "snappy": "^7.2.2" 488 | }, 489 | "peerDependenciesMeta": { 490 | "@aws-sdk/credential-providers": { 491 | "optional": true 492 | }, 493 | "mongodb-client-encryption": { 494 | "optional": true 495 | }, 496 | "snappy": { 497 | "optional": true 498 | } 499 | } 500 | }, 501 | "node_modules/mongodb-connection-string-url": { 502 | "version": "2.6.0", 503 | "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", 504 | "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", 505 | "dependencies": { 506 | "@types/whatwg-url": "^8.2.1", 507 | "whatwg-url": "^11.0.0" 508 | } 509 | }, 510 | "node_modules/mongoose": { 511 | "version": "7.0.3", 512 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.0.3.tgz", 513 | "integrity": "sha512-3n8vc1/mssuxKa6vfghSocp3MeiCFYzhX36Ok+PsDNNYzHC9tw3rNkAMLemIwZ2jgXqkZ7CfKOxkzjp/d/SWfg==", 514 | "dependencies": { 515 | "bson": "^5.0.1", 516 | "kareem": "2.5.1", 517 | "mongodb": "5.1.0", 518 | "mpath": "0.9.0", 519 | "mquery": "5.0.0", 520 | "ms": "2.1.3", 521 | "sift": "16.0.1" 522 | }, 523 | "engines": { 524 | "node": ">=14.0.0" 525 | }, 526 | "funding": { 527 | "type": "opencollective", 528 | "url": "https://opencollective.com/mongoose" 529 | } 530 | }, 531 | "node_modules/mongoose/node_modules/ms": { 532 | "version": "2.1.3", 533 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 534 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 535 | }, 536 | "node_modules/mpath": { 537 | "version": "0.9.0", 538 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", 539 | "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", 540 | "engines": { 541 | "node": ">=4.0.0" 542 | } 543 | }, 544 | "node_modules/mquery": { 545 | "version": "5.0.0", 546 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", 547 | "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", 548 | "dependencies": { 549 | "debug": "4.x" 550 | }, 551 | "engines": { 552 | "node": ">=14.0.0" 553 | } 554 | }, 555 | "node_modules/mquery/node_modules/debug": { 556 | "version": "4.3.4", 557 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 558 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 559 | "dependencies": { 560 | "ms": "2.1.2" 561 | }, 562 | "engines": { 563 | "node": ">=6.0" 564 | }, 565 | "peerDependenciesMeta": { 566 | "supports-color": { 567 | "optional": true 568 | } 569 | } 570 | }, 571 | "node_modules/mquery/node_modules/ms": { 572 | "version": "2.1.2", 573 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 574 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 575 | }, 576 | "node_modules/ms": { 577 | "version": "2.0.0", 578 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 579 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 580 | }, 581 | "node_modules/negotiator": { 582 | "version": "0.6.3", 583 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 584 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 585 | "engines": { 586 | "node": ">= 0.6" 587 | } 588 | }, 589 | "node_modules/object-assign": { 590 | "version": "4.1.1", 591 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 592 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 593 | "engines": { 594 | "node": ">=0.10.0" 595 | } 596 | }, 597 | "node_modules/object-inspect": { 598 | "version": "1.12.3", 599 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 600 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 601 | "funding": { 602 | "url": "https://github.com/sponsors/ljharb" 603 | } 604 | }, 605 | "node_modules/on-finished": { 606 | "version": "2.4.1", 607 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 608 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 609 | "dependencies": { 610 | "ee-first": "1.1.1" 611 | }, 612 | "engines": { 613 | "node": ">= 0.8" 614 | } 615 | }, 616 | "node_modules/parseurl": { 617 | "version": "1.3.3", 618 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 619 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 620 | "engines": { 621 | "node": ">= 0.8" 622 | } 623 | }, 624 | "node_modules/path-to-regexp": { 625 | "version": "0.1.7", 626 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 627 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 628 | }, 629 | "node_modules/proxy-addr": { 630 | "version": "2.0.7", 631 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 632 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 633 | "dependencies": { 634 | "forwarded": "0.2.0", 635 | "ipaddr.js": "1.9.1" 636 | }, 637 | "engines": { 638 | "node": ">= 0.10" 639 | } 640 | }, 641 | "node_modules/punycode": { 642 | "version": "2.3.0", 643 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 644 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 645 | "engines": { 646 | "node": ">=6" 647 | } 648 | }, 649 | "node_modules/qs": { 650 | "version": "6.11.0", 651 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 652 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 653 | "dependencies": { 654 | "side-channel": "^1.0.4" 655 | }, 656 | "engines": { 657 | "node": ">=0.6" 658 | }, 659 | "funding": { 660 | "url": "https://github.com/sponsors/ljharb" 661 | } 662 | }, 663 | "node_modules/range-parser": { 664 | "version": "1.2.1", 665 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 666 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 667 | "engines": { 668 | "node": ">= 0.6" 669 | } 670 | }, 671 | "node_modules/raw-body": { 672 | "version": "2.5.2", 673 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 674 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 675 | "dependencies": { 676 | "bytes": "3.1.2", 677 | "http-errors": "2.0.0", 678 | "iconv-lite": "0.4.24", 679 | "unpipe": "1.0.0" 680 | }, 681 | "engines": { 682 | "node": ">= 0.8" 683 | } 684 | }, 685 | "node_modules/safe-buffer": { 686 | "version": "5.2.1", 687 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 688 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 689 | "funding": [ 690 | { 691 | "type": "github", 692 | "url": "https://github.com/sponsors/feross" 693 | }, 694 | { 695 | "type": "patreon", 696 | "url": "https://www.patreon.com/feross" 697 | }, 698 | { 699 | "type": "consulting", 700 | "url": "https://feross.org/support" 701 | } 702 | ] 703 | }, 704 | "node_modules/safer-buffer": { 705 | "version": "2.1.2", 706 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 707 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 708 | }, 709 | "node_modules/saslprep": { 710 | "version": "1.0.3", 711 | "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", 712 | "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", 713 | "optional": true, 714 | "dependencies": { 715 | "sparse-bitfield": "^3.0.3" 716 | }, 717 | "engines": { 718 | "node": ">=6" 719 | } 720 | }, 721 | "node_modules/send": { 722 | "version": "0.18.0", 723 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 724 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 725 | "dependencies": { 726 | "debug": "2.6.9", 727 | "depd": "2.0.0", 728 | "destroy": "1.2.0", 729 | "encodeurl": "~1.0.2", 730 | "escape-html": "~1.0.3", 731 | "etag": "~1.8.1", 732 | "fresh": "0.5.2", 733 | "http-errors": "2.0.0", 734 | "mime": "1.6.0", 735 | "ms": "2.1.3", 736 | "on-finished": "2.4.1", 737 | "range-parser": "~1.2.1", 738 | "statuses": "2.0.1" 739 | }, 740 | "engines": { 741 | "node": ">= 0.8.0" 742 | } 743 | }, 744 | "node_modules/send/node_modules/ms": { 745 | "version": "2.1.3", 746 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 747 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 748 | }, 749 | "node_modules/serve-static": { 750 | "version": "1.15.0", 751 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 752 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 753 | "dependencies": { 754 | "encodeurl": "~1.0.2", 755 | "escape-html": "~1.0.3", 756 | "parseurl": "~1.3.3", 757 | "send": "0.18.0" 758 | }, 759 | "engines": { 760 | "node": ">= 0.8.0" 761 | } 762 | }, 763 | "node_modules/setprototypeof": { 764 | "version": "1.2.0", 765 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 766 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 767 | }, 768 | "node_modules/side-channel": { 769 | "version": "1.0.4", 770 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 771 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 772 | "dependencies": { 773 | "call-bind": "^1.0.0", 774 | "get-intrinsic": "^1.0.2", 775 | "object-inspect": "^1.9.0" 776 | }, 777 | "funding": { 778 | "url": "https://github.com/sponsors/ljharb" 779 | } 780 | }, 781 | "node_modules/sift": { 782 | "version": "16.0.1", 783 | "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", 784 | "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" 785 | }, 786 | "node_modules/smart-buffer": { 787 | "version": "4.2.0", 788 | "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", 789 | "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", 790 | "engines": { 791 | "node": ">= 6.0.0", 792 | "npm": ">= 3.0.0" 793 | } 794 | }, 795 | "node_modules/socks": { 796 | "version": "2.7.1", 797 | "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", 798 | "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", 799 | "dependencies": { 800 | "ip": "^2.0.0", 801 | "smart-buffer": "^4.2.0" 802 | }, 803 | "engines": { 804 | "node": ">= 10.13.0", 805 | "npm": ">= 3.0.0" 806 | } 807 | }, 808 | "node_modules/sparse-bitfield": { 809 | "version": "3.0.3", 810 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 811 | "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", 812 | "optional": true, 813 | "dependencies": { 814 | "memory-pager": "^1.0.2" 815 | } 816 | }, 817 | "node_modules/statuses": { 818 | "version": "2.0.1", 819 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 820 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 821 | "engines": { 822 | "node": ">= 0.8" 823 | } 824 | }, 825 | "node_modules/toidentifier": { 826 | "version": "1.0.1", 827 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 828 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 829 | "engines": { 830 | "node": ">=0.6" 831 | } 832 | }, 833 | "node_modules/tr46": { 834 | "version": "3.0.0", 835 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", 836 | "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", 837 | "dependencies": { 838 | "punycode": "^2.1.1" 839 | }, 840 | "engines": { 841 | "node": ">=12" 842 | } 843 | }, 844 | "node_modules/type-is": { 845 | "version": "1.6.18", 846 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 847 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 848 | "dependencies": { 849 | "media-typer": "0.3.0", 850 | "mime-types": "~2.1.24" 851 | }, 852 | "engines": { 853 | "node": ">= 0.6" 854 | } 855 | }, 856 | "node_modules/unpipe": { 857 | "version": "1.0.0", 858 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 859 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 860 | "engines": { 861 | "node": ">= 0.8" 862 | } 863 | }, 864 | "node_modules/utils-merge": { 865 | "version": "1.0.1", 866 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 867 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 868 | "engines": { 869 | "node": ">= 0.4.0" 870 | } 871 | }, 872 | "node_modules/vary": { 873 | "version": "1.1.2", 874 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 875 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 876 | "engines": { 877 | "node": ">= 0.8" 878 | } 879 | }, 880 | "node_modules/webidl-conversions": { 881 | "version": "7.0.0", 882 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 883 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", 884 | "engines": { 885 | "node": ">=12" 886 | } 887 | }, 888 | "node_modules/whatwg-url": { 889 | "version": "11.0.0", 890 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", 891 | "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", 892 | "dependencies": { 893 | "tr46": "^3.0.0", 894 | "webidl-conversions": "^7.0.0" 895 | }, 896 | "engines": { 897 | "node": ">=12" 898 | } 899 | } 900 | } 901 | } 902 | --------------------------------------------------------------------------------