├── week-6 ├── 3-use-ref │ ├── src │ │ ├── App.css │ │ ├── index.css │ │ ├── main.jsx │ │ ├── App.jsx │ │ └── components │ │ │ ├── Assignment1.jsx │ │ │ └── Assignment2.jsx │ ├── vite.config.js │ ├── .gitignore │ ├── index.html │ ├── README.md │ ├── .eslintrc.cjs │ ├── package.json │ └── public │ │ └── vite.svg ├── 1-use-memo │ ├── src │ │ ├── App.css │ │ ├── index.css │ │ ├── main.jsx │ │ ├── App.jsx │ │ └── components │ │ │ ├── Assignment1.jsx │ │ │ ├── Assignment3.jsx │ │ │ └── Assignment2.jsx │ ├── vite.config.js │ ├── .gitignore │ ├── index.html │ ├── README.md │ ├── .eslintrc.cjs │ ├── package.json │ └── public │ │ └── vite.svg ├── 2-use-callback │ ├── src │ │ ├── App.css │ │ ├── index.css │ │ ├── main.jsx │ │ ├── App.jsx │ │ └── components │ │ │ ├── Assignment1.jsx │ │ │ └── Assignment2.jsx │ ├── vite.config.js │ ├── .gitignore │ ├── index.html │ ├── README.md │ ├── .eslintrc.cjs │ ├── package.json │ └── public │ │ └── vite.svg ├── README.md └── solutions │ ├── 1 │ └── components │ │ ├── Assignment1.jsx │ │ ├── Assignment3.jsx │ │ └── Assignment2.jsx │ ├── 2 │ └── components │ │ ├── Assignment1.jsx │ │ └── Assignment2.jsx │ └── 3 │ └── components │ ├── Assignment1.jsx │ └── Assignment2.jsx ├── week-2 ├── 02-nodejs │ ├── todos.json │ ├── .gitignore │ ├── files │ │ └── a.txt │ ├── package.json │ ├── fileServer.js │ ├── README.md │ ├── solutions │ │ ├── fileServer.solution.js │ │ ├── todoServer.solution.file.js │ │ └── todoServer.solution.js │ ├── todoServer.js │ └── tests │ │ ├── todoServer.test.js │ │ └── fileServer.test.js └── 01-async-js │ ├── .gitignore │ ├── temp.txt │ ├── easy │ ├── 01-counter.js │ ├── 4-write-to-file.md │ ├── 02-counter.js │ ├── 1-counter.md │ ├── 04-write-to-file.js │ ├── 3-read-from-file.md │ ├── 03-read-from-file.js │ └── 2-counter.md │ ├── medium │ ├── 02-clock.js │ ├── 2-clock.md │ ├── 1-file-cleaner.md │ └── 01-file-cleaner.js │ ├── hard (promises) │ ├── 1-promisify-setTimeout.js │ ├── 2-sleep-completely.js │ ├── 3-promise-all.js │ └── 4-promise-chain.js │ ├── package.json │ ├── tests │ ├── 4-promise-chain.test.js │ ├── 3-promise-all.test.js │ ├── 1-promisify-setTimeout.test.js │ └── 2-sleep-completely.test.js │ └── README.md ├── week-3 ├── 01-middlewares │ ├── index.js │ ├── .gitignore │ ├── jest.config.ts │ ├── package.json │ ├── 01-requestcount.js │ ├── 03-errorcount.js │ ├── tests │ │ ├── 01-requestcount.spec.js │ │ ├── 03-errorcount.spec.js │ │ └── 02-ratelimitter.spec.js │ ├── 02-ratelimitter.js │ └── tsconfig.json ├── 02-jwt │ ├── .gitignore │ ├── package.json │ ├── index.js │ ├── tests │ │ └── index.spec.js │ ├── tsconfig.json │ └── package-lock.json ├── 03-mongo │ ├── .gitignore │ ├── middleware │ │ ├── user.js │ │ └── admin.js │ ├── index.js │ ├── package.json │ ├── routes │ │ ├── admin.js │ │ └── user.js │ ├── db │ │ └── index.js │ ├── solution │ │ ├── middleware │ │ │ ├── user.js │ │ │ └── admin.js │ │ ├── db │ │ │ └── index.js │ │ └── routes │ │ │ ├── admin.js │ │ │ └── user.js │ └── README.md ├── 04-mongo-with-jwt-auth │ ├── .gitignore │ ├── middleware │ │ ├── user.js │ │ └── admin.js │ ├── index.js │ ├── package.json │ ├── routes │ │ ├── admin.js │ │ └── user.js │ ├── db │ │ └── index.js │ ├── solution │ │ ├── middleware │ │ │ ├── user.js │ │ │ └── admin.js │ │ ├── routes │ │ │ ├── user.js │ │ │ └── admin.js │ │ └── db │ │ │ └── index.js │ └── README.md ├── solutions │ ├── 01-requestcount.js │ ├── 03-errorcount.js │ ├── 02.js │ └── 02-ratelimitter.js └── README.md ├── week-5 ├── level-1 │ ├── BusinessCard.png │ └── README.md └── solutions │ └── level-1 │ └── BusinessCard.jsx ├── 01-js ├── package-lock.json ├── package.json ├── easy │ ├── findLargestElement.js │ ├── anagram.js │ └── expenditure-analysis.js ├── medium │ ├── palindrome.js │ ├── countVowels.js │ └── times.js ├── README.md ├── tests │ ├── findLargestElement.test.js │ ├── anagram.test.js │ ├── countVowels.test.js │ ├── palindrome.test.js │ ├── todo-list.test.js │ ├── expenditure-analysis.test.js │ └── calculator.test.js └── hard │ ├── todo-list.js │ └── calculator.js ├── week-1 └── offline-class-1 │ ├── level-2 │ ├── 01-Class.js │ ├── 03-JSON.js │ ├── 05-Object.js │ ├── 04-Math.js │ └── 02-Date.js │ └── level-1 │ ├── 02-Number.js │ ├── 01-String.js │ └── 03-Array.js └── week-4 ├── react-basics └── README.md ├── README.md └── index.html /week-6/3-use-ref/src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-2/02-nodejs/todos.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /week-3/01-middlewares/index.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-6/1-use-memo/src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-6/1-use-memo/src/index.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-6/2-use-callback/src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-6/3-use-ref/src/index.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-6/2-use-callback/src/index.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-3/02-jwt/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /week-3/03-mongo/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /week-2/02-nodejs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /week-2/02-nodejs/files/a.txt: -------------------------------------------------------------------------------- 1 | hello from a.txt -------------------------------------------------------------------------------- /week-3/01-middlewares/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /week-2/01-async-js/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | solutions -------------------------------------------------------------------------------- /week-2/01-async-js/temp.txt: -------------------------------------------------------------------------------- 1 | this is the new line i added -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /week-5/level-1/BusinessCard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshDev56/100xDevs_MERN_assignments/HEAD/week-5/level-1/BusinessCard.png -------------------------------------------------------------------------------- /week-2/01-async-js/easy/01-counter.js: -------------------------------------------------------------------------------- 1 | function counter(counter) { 2 | setInterval(() => { 3 | console.log(counter++); 4 | }, 1000); 5 | } 6 | 7 | counter(1); -------------------------------------------------------------------------------- /week-3/01-middlewares/jest.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | clearMocks: true, 3 | collectCoverage: true, 4 | coverageDirectory: 'coverage', 5 | coverageProvider: 'v8', 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /week-2/01-async-js/easy/4-write-to-file.md: -------------------------------------------------------------------------------- 1 | ## Write to a file 2 | Using the fs library again, try to write to the contents of a file. 3 | You can use the fs library to as a black box, the goal is to understand async tasks. -------------------------------------------------------------------------------- /week-6/1-use-memo/vite.config.js: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /week-6/3-use-ref/vite.config.js: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /week-6/2-use-callback/vite.config.js: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /week-2/01-async-js/easy/02-counter.js: -------------------------------------------------------------------------------- 1 | function countWithoutInterval(count) { 2 | setTimeout(() => { 3 | console.log(count++); 4 | countWithoutInterval(count); 5 | }, 1000); 6 | } 7 | 8 | countWithoutInterval(1) -------------------------------------------------------------------------------- /week-2/01-async-js/easy/1-counter.md: -------------------------------------------------------------------------------- 1 | ## Create a counter in JavaScript 2 | 3 | We have already covered this in the second lesson, but as an easy recap try to code a counter in Javascript 4 | It should go up as time goes by in intervals of 1 second -------------------------------------------------------------------------------- /01-js/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "01", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "01", 9 | "version": "1.0.0", 10 | "license": "ISC" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /week-1/offline-class-1/level-2/01-Class.js: -------------------------------------------------------------------------------- 1 | 2 | class Animal { 3 | constructor(name, legCount) { 4 | this.name = name 5 | this.legCount = legCount 6 | } 7 | describe() { 8 | return `${this.name} has ${this.legCount} legs` 9 | } 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /week-3/03-mongo/middleware/user.js: -------------------------------------------------------------------------------- 1 | function userMiddleware(req, res, next) { 2 | // Implement user auth logic 3 | // You need to check the headers and validate the user from the user DB. Check readme for the exact headers to be expected 4 | } 5 | 6 | module.exports = userMiddleware; -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/middleware/user.js: -------------------------------------------------------------------------------- 1 | function userMiddleware(req, res, next) { 2 | // Implement user auth logic 3 | // You need to check the headers and validate the user from the user DB. Check readme for the exact headers to be expected 4 | } 5 | 6 | module.exports = userMiddleware; -------------------------------------------------------------------------------- /week-2/01-async-js/easy/04-write-to-file.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | let data = " this is the new line i added "; 4 | fs.writeFile("../temp.txt", data, (err) => { 5 | if (err) { 6 | console.log(err); 7 | } else { 8 | console.log("Success"); 9 | } 10 | }) -------------------------------------------------------------------------------- /week-6/1-use-memo/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /week-6/3-use-ref/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /week-6/2-use-callback/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /week-3/03-mongo/middleware/admin.js: -------------------------------------------------------------------------------- 1 | // Middleware for handling auth 2 | function adminMiddleware(req, res, next) { 3 | // Implement admin auth logic 4 | // You need to check the headers and validate the admin from the admin DB. Check readme for the exact headers to be expected 5 | } 6 | 7 | module.exports = adminMiddleware; -------------------------------------------------------------------------------- /week-2/01-async-js/medium/02-clock.js: -------------------------------------------------------------------------------- 1 | function clock() { 2 | setInterval(() => { 3 | let date = new Date(); 4 | let hour = date.getHours(); 5 | // HH:MM::SS AM/PM 6 | console.log(hour + ":" + date.getMinutes() + ":" + date.getSeconds(), hour > 12 ? "PM" : "AM"); 7 | }, 1000) 8 | } 9 | 10 | clock() -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/middleware/admin.js: -------------------------------------------------------------------------------- 1 | // Middleware for handling auth 2 | function adminMiddleware(req, res, next) { 3 | // Implement admin auth logic 4 | // You need to check the headers and validate the admin from the admin DB. Check readme for the exact headers to be expected 5 | } 6 | 7 | module.exports = adminMiddleware; -------------------------------------------------------------------------------- /week-2/01-async-js/medium/2-clock.md: -------------------------------------------------------------------------------- 1 | Using `1-counter.md` or `2-counter.md` from the easy section, can you create a 2 | clock that shows you the current machine time? 3 | 4 | Can you make it so that it updates every second, and shows time in the following formats - 5 | 6 | - HH:MM::SS (Eg. 13:45:23) 7 | 8 | - HH:MM::SS AM/PM (Eg 01:45:23 PM) 9 | -------------------------------------------------------------------------------- /week-6/3-use-ref/src/App.jsx: -------------------------------------------------------------------------------- 1 | import './App.css' 2 | import { Assignment1 } from './components/Assignment1' 3 | import { Assignment2 } from './components/Assignment2' 4 | 5 | function App() { 6 | return ( 7 | <> 8 | 9 | {/* */} 10 | 11 | ) 12 | } 13 | 14 | export default App 15 | -------------------------------------------------------------------------------- /week-6/2-use-callback/src/App.jsx: -------------------------------------------------------------------------------- 1 | import './App.css' 2 | import { Assignment1 } from './components/Assignment1' 3 | import { Assignment2 } from './components/Assignment2' 4 | 5 | function App() { 6 | return ( 7 | <> 8 | {/* */} 9 | 10 | 11 | ) 12 | } 13 | 14 | export default App 15 | -------------------------------------------------------------------------------- /week-6/README.md: -------------------------------------------------------------------------------- 1 | ## React hook assignments 2 | You will find a bunch of folders this week, each with some set of assignments for a specific hook 3 | Go to the folder (for example 1-use-memo) and comment out the Assignment component you are working on (Assignment1/Assignment2...) and try to solve it 4 | There are no tests, but solution videos will be provided -------------------------------------------------------------------------------- /week-2/01-async-js/medium/1-file-cleaner.md: -------------------------------------------------------------------------------- 1 | ## File cleaner 2 | Read a file, remove all the extra spaces and write it back to the same file. 3 | 4 | For example, if the file input was 5 | ``` 6 | hello world my name is raman 7 | ``` 8 | 9 | After the program runs, the output should be 10 | 11 | ``` 12 | hello world my name is raman 13 | ``` -------------------------------------------------------------------------------- /week-3/02-jwt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "02-jwt", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "jsonwebtoken": "^9.0.2", 14 | "zod": "^3.22.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /week-6/1-use-memo/.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 | -------------------------------------------------------------------------------- /week-6/3-use-ref/.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 | -------------------------------------------------------------------------------- /week-6/2-use-callback/.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 | -------------------------------------------------------------------------------- /week-2/01-async-js/easy/3-read-from-file.md: -------------------------------------------------------------------------------- 1 | ## Reading the contents of a file 2 | 3 | Write code to read contents of a file and print it to the console. 4 | You can use the fs library to as a black box, the goal is to understand async tasks. 5 | Try to do an expensive operation below the file read and see how it affects the output. 6 | Make the expensive operation more and more expensive and see how it affects the output. 7 | 8 | -------------------------------------------------------------------------------- /week-6/1-use-memo/src/App.jsx: -------------------------------------------------------------------------------- 1 | import './App.css' 2 | import { Assignment1 } from './components/Assignment1' 3 | import { Assignment2 } from './components/Assignment2' 4 | import { Assignment3 } from './components/Assignment3' 5 | 6 | function App() { 7 | return ( 8 | <> 9 | 10 | {/* */} 11 | {/* */} 12 | 13 | ) 14 | } 15 | 16 | export default App 17 | -------------------------------------------------------------------------------- /week-2/01-async-js/easy/03-read-from-file.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | fs.readFile("../temp.txt", "utf-8", (err, data) => { 4 | if (err) { 5 | console.log("Something wrong " + err.message); 6 | } else { 7 | console.log(data); 8 | } 9 | }) 10 | 11 | // expensive operation 12 | let counter = 0; 13 | for (let index = 0; index < 1000000000; index++) { 14 | counter++; 15 | } 16 | 17 | console.log(counter); -------------------------------------------------------------------------------- /week-2/01-async-js/hard (promises)/1-promisify-setTimeout.js: -------------------------------------------------------------------------------- 1 | /* 2 | Write a function that returns a promise that resolves after n seconds have passed, where n is passed as an argument to the function. 3 | */ 4 | 5 | function wait(n) { 6 | return new Promise((resolve, reject) => { 7 | 8 | setTimeout(() => { 9 | resolve() 10 | }, n * 1000); 11 | 12 | }) 13 | 14 | } 15 | 16 | module.exports = wait; 17 | -------------------------------------------------------------------------------- /week-6/1-use-memo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /week-6/3-use-ref/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /week-6/2-use-callback/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /week-6/1-use-memo/README.md: -------------------------------------------------------------------------------- 1 | # React + 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 | -------------------------------------------------------------------------------- /week-6/3-use-ref/README.md: -------------------------------------------------------------------------------- 1 | # React + 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 | -------------------------------------------------------------------------------- /week-6/2-use-callback/README.md: -------------------------------------------------------------------------------- 1 | # React + 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 | -------------------------------------------------------------------------------- /week-3/03-mongo/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | const app = express(); 4 | const adminRouter = require("./routes/admin") 5 | const userRouter = require("./routes/user"); 6 | 7 | // Middleware for parsing request bodies 8 | app.use(bodyParser.json()); 9 | app.use("/admin", adminRouter) 10 | app.use("/user", userRouter) 11 | 12 | const PORT = 3000; 13 | 14 | app.listen(PORT, () => { 15 | console.log(`Server is running on port ${PORT}`); 16 | }); 17 | -------------------------------------------------------------------------------- /01-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "01", 3 | "version": "1.0.0", 4 | "description": "You are provided empty JavaScript files (or having function signatures) in this directory. You have to follow the instructions given in each file and write the code in the same file to complete the assignment.", 5 | "main": "anagram.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "jest": "^29.7.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | const app = express(); 4 | const adminRouter = require("./routes/admin") 5 | const userRouter = require("./routes/user"); 6 | 7 | // Middleware for parsing request bodies 8 | app.use(bodyParser.json()); 9 | app.use("/admin", adminRouter) 10 | app.use("/user", userRouter) 11 | 12 | const PORT = 3000; 13 | app.listen(PORT, () => { 14 | console.log(`Server is running on port ${PORT}`); 15 | }); 16 | -------------------------------------------------------------------------------- /01-js/easy/findLargestElement.js: -------------------------------------------------------------------------------- 1 | /* 2 | Write a function `findLargestElement` that takes an array of numbers and returns the largest element. 3 | Example: 4 | - Input: [3, 7, 2, 9, 1] 5 | - Output: 9 6 | */ 7 | 8 | function findLargestElement(numbers) { 9 | let max = numbers[0]; 10 | for (let index = 1; index < numbers.length; index++) { 11 | if (numbers[index] > max) { 12 | max = numbers[index]; 13 | } 14 | } 15 | return max; 16 | } 17 | 18 | module.exports = findLargestElement; -------------------------------------------------------------------------------- /week-3/03-mongo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "03-mongo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@babel/plugin-transform-modules-commonjs": "^7.23.3", 14 | "express": "^4.18.2", 15 | "jest": "^29.7.0", 16 | "mongoose": "^8.0.3", 17 | "supertest": "^6.3.3", 18 | "ts-node": "^10.9.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /week-2/01-async-js/hard (promises)/2-sleep-completely.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Write a function that halts the JS thread (make it busy wait) for a given number of milliseconds. 3 | * During this time the thread should not be able to do anything else. 4 | * the function should return a promise just like before 5 | */ 6 | 7 | function sleep(milliseconds) { 8 | let time = new Date().getTime(); 9 | while (new Date().getTime() - time < milliseconds) { } 10 | return new Promise((resolve) => { resolve() }); 11 | } 12 | 13 | module.exports = sleep; 14 | -------------------------------------------------------------------------------- /week-3/03-mongo/routes/admin.js: -------------------------------------------------------------------------------- 1 | const { Router } = require("express"); 2 | const adminMiddleware = require("../middleware/admin"); 3 | const router = Router(); 4 | 5 | // Admin Routes 6 | router.post('/signup', (req, res) => { 7 | // Implement admin signup logic 8 | }); 9 | 10 | router.post('/courses', adminMiddleware, (req, res) => { 11 | // Implement course creation logic 12 | }); 13 | 14 | router.get('/courses', adminMiddleware, (req, res) => { 15 | // Implement fetching all courses logic 16 | }); 17 | 18 | module.exports = router; -------------------------------------------------------------------------------- /week-2/01-async-js/medium/01-file-cleaner.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | fs.readFile("../temp.txt", "utf-8", (error, data) => { 4 | if (error) { 5 | console.log(error.message); 6 | } else { 7 | data = data.replace(/\s+/g, " ") 8 | writeNewStr(data); 9 | } 10 | }) 11 | 12 | 13 | function writeNewStr(data) { 14 | fs.writeFile("../temp.txt", data, (error) => { 15 | if (error) { 16 | console.log(error); 17 | } else { 18 | console.log("Sucesss"); 19 | } 20 | }) 21 | } -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "03-mongo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@babel/plugin-transform-modules-commonjs": "^7.23.3", 14 | "express": "^4.18.2", 15 | "jest": "^29.7.0", 16 | "mongoose": "^8.0.3", 17 | "supertest": "^6.3.3", 18 | "ts-node": "^10.9.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /week-3/01-middlewares/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "01-middlewares", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.18.2", 14 | "jest": "^29.7.0", 15 | "supertest": "^6.3.3" 16 | }, 17 | "devDependencies": { 18 | "@babel/plugin-transform-modules-commonjs": "^7.23.3", 19 | "eslint-plugin-jest": "^27.6.0", 20 | "ts-node": "^10.9.2" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /week-2/01-async-js/easy/2-counter.md: -------------------------------------------------------------------------------- 1 | ## Counter without setInterval 2 | 3 | Without using setInterval, try to code a counter in Javascript. There is a hint at the bottom of the file if you get stuck. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | (Hint: setTimeout) -------------------------------------------------------------------------------- /week-6/1-use-memo/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react-refresh/only-export-components': [ 16 | 'warn', 17 | { allowConstantExport: true }, 18 | ], 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /week-6/3-use-ref/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react-refresh/only-export-components': [ 16 | 'warn', 17 | { allowConstantExport: true }, 18 | ], 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /week-6/3-use-ref/src/components/Assignment1.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | // Create a component with a text input field and a button. When the component mounts or the button is clicked, automatically focus the text input field using useRef. 4 | 5 | export function Assignment1() { 6 | 7 | useEffect(() => { 8 | 9 | }, []); 10 | 11 | const handleButtonClick = () => { 12 | 13 | }; 14 | 15 | return ( 16 |
17 | 18 | 19 |
20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /week-6/2-use-callback/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react-refresh/only-export-components': [ 16 | 'warn', 17 | { allowConstantExport: true }, 18 | ], 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /week-1/offline-class-1/level-1/02-Number.js: -------------------------------------------------------------------------------- 1 | function explainParseInt(value) { 2 | console.log("Original Value:", value); 3 | let result = parseInt(value); 4 | console.log("After parseInt:", result); 5 | } 6 | 7 | // Example Usage for parseInt 8 | explainParseInt("42"); 9 | explainParseInt("42px"); 10 | explainParseInt("3.14"); 11 | 12 | function explainParseFloat(value) { 13 | console.log("Original Value:", value); 14 | let result = parseFloat(value); 15 | console.log("After parseFloat:", result); 16 | } 17 | 18 | // Example Usage for parseFloat 19 | explainParseFloat("3.14"); 20 | explainParseFloat("42"); 21 | explainParseFloat("42px"); 22 | -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/routes/admin.js: -------------------------------------------------------------------------------- 1 | const { Router } = require("express"); 2 | const adminMiddleware = require("../middleware/admin"); 3 | const router = Router(); 4 | 5 | // Admin Routes 6 | router.post('/signup', (req, res) => { 7 | // Implement admin signup logic 8 | }); 9 | 10 | router.post('/signin', (req, res) => { 11 | // Implement admin signup logic 12 | }); 13 | 14 | router.post('/courses', adminMiddleware, (req, res) => { 15 | // Implement course creation logic 16 | }); 17 | 18 | router.get('/courses', adminMiddleware, (req, res) => { 19 | // Implement fetching all courses logic 20 | }); 21 | 22 | module.exports = router; -------------------------------------------------------------------------------- /week-4/react-basics/README.md: -------------------------------------------------------------------------------- 1 | Try to bootstrap a basic React application using vite. 2 | Read more about vite here - https://vitejs.dev/ 3 | 4 | Create the following functionality - 5 | - A basic TODO application where there are two input (title and description) boxes and users can add append TODOs to a div 6 | - Try using the same DOM functionality we did in week 4. Don't try to use state variables in React just yet 7 | - Just tro to port over our original HTML/JS impelementation over to a React project 8 | - Hard todo - If you can, try using `useState` that we discussed this week and propogate the TODOs using state (If you don't understand this, dont worry about it) -------------------------------------------------------------------------------- /week-3/03-mongo/routes/user.js: -------------------------------------------------------------------------------- 1 | const { Router } = require("express"); 2 | const router = Router(); 3 | const userMiddleware = require("../middleware/user"); 4 | 5 | // User Routes 6 | router.post('/signup', (req, res) => { 7 | // Implement user signup logic 8 | }); 9 | 10 | router.get('/courses', (req, res) => { 11 | // Implement listing all courses logic 12 | }); 13 | 14 | router.post('/courses/:courseId', userMiddleware, (req, res) => { 15 | // Implement course purchase logic 16 | }); 17 | 18 | router.get('/purchasedCourses', userMiddleware, (req, res) => { 19 | // Implement fetching purchased courses logic 20 | }); 21 | 22 | module.exports = router -------------------------------------------------------------------------------- /week-1/offline-class-1/level-2/03-JSON.js: -------------------------------------------------------------------------------- 1 | function jsonMethods(jsonString) { 2 | console.log("Original JSON String:", jsonString); 3 | 4 | // Parsing JSON string to JavaScript object 5 | let parsedObject = JSON.parse(jsonString); 6 | console.log("After JSON.parse():", parsedObject); 7 | 8 | // Stringifying JavaScript object to JSON string 9 | let jsonStringified = JSON.stringify(parsedObject); 10 | console.log("After JSON.stringify():", jsonStringified); 11 | } 12 | 13 | // Example Usage for JSON Methods 14 | const sampleJSONString = 15 | '{"key": "value", "number": 42, "nested": {"nestedKey": "nestedValue"}}'; 16 | 17 | jsonMethods(sampleJSONString); 18 | -------------------------------------------------------------------------------- /01-js/easy/anagram.js: -------------------------------------------------------------------------------- 1 | /* 2 | Write a function `isAnagram` which takes 2 parameters and returns true/false if those are anagrams or not. 3 | What's Anagram? 4 | - A word, phrase, or name formed by rearranging the letters of another, such as spar, formed from rasp. 5 | */ 6 | 7 | function isAnagram(str1, str2) { 8 | str1 = sortString(str1.toLowerCase()); 9 | str2 = sortString(str2.toLowerCase()); 10 | if (str1 === str2) { 11 | return true; 12 | } 13 | return false; 14 | } 15 | 16 | function sortString(str) { 17 | let charArray = str.split('') 18 | charArray.sort(); 19 | let ans = charArray.join('') 20 | return ans; 21 | } 22 | 23 | module.exports = isAnagram; 24 | -------------------------------------------------------------------------------- /week-3/03-mongo/db/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | // Connect to MongoDB 4 | mongoose.connect('your-mongodb-url'); 5 | 6 | // Define schemas 7 | const AdminSchema = new mongoose.Schema({ 8 | // Schema definition here 9 | }); 10 | 11 | const UserSchema = new mongoose.Schema({ 12 | // Schema definition here 13 | }); 14 | 15 | const CourseSchema = new mongoose.Schema({ 16 | // Schema definition here 17 | }); 18 | 19 | const Admin = mongoose.model('Admin', AdminSchema); 20 | const User = mongoose.model('User', UserSchema); 21 | const Course = mongoose.model('Course', CourseSchema); 22 | 23 | module.exports = { 24 | Admin, 25 | User, 26 | Course 27 | } -------------------------------------------------------------------------------- /week-2/01-async-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "01-async", 3 | "version": "1.0.0", 4 | "description": "This folder contains assignments related to asynchronous JavaScript.", 5 | "main": "index.js", 6 | "scripts": { 7 | "1-promisify-setTimeout": "npx jest ./tests/1-promisify-setTimeout.test.js", 8 | "2-sleep-completely": "npx jest ./tests/2-sleep-completely.test.js", 9 | "3-promise-all": "npx jest ./tests/3-promise-all.test.js", 10 | "4-promise-chain": "npx jest ./tests/4-promise-chain.test.js", 11 | "all": "npx jest ./tests/" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "jest": "^29.7.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/db/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | // Connect to MongoDB 4 | mongoose.connect('your-mongodb-url'); 5 | 6 | // Define schemas 7 | const AdminSchema = new mongoose.Schema({ 8 | // Schema definition here 9 | }); 10 | 11 | const UserSchema = new mongoose.Schema({ 12 | // Schema definition here 13 | }); 14 | 15 | const CourseSchema = new mongoose.Schema({ 16 | // Schema definition here 17 | }); 18 | 19 | const Admin = mongoose.model('Admin', AdminSchema); 20 | const User = mongoose.model('User', UserSchema); 21 | const Course = mongoose.model('Course', CourseSchema); 22 | 23 | module.exports = { 24 | Admin, 25 | User, 26 | Course 27 | } -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/solution/middleware/user.js: -------------------------------------------------------------------------------- 1 | const {JWT_SECRET} = require("../config"); 2 | const jwt = require("jsonwebtoken"); 3 | 4 | function userMiddleware(req, res, next) { 5 | const token = req.headers.authorization; 6 | const words = token.split(" "); 7 | const jwtToken = words[1]; 8 | const decodedValue = jwt.verify(jwtToken, JWT_SECRET); 9 | 10 | if (decodedValue.username) { 11 | req.username = decodedValue.username; 12 | req.randomData = "Adsadsadsadssd"; 13 | next(); 14 | } else { 15 | res.status(403).json({ 16 | msg: "You are not authenticated" 17 | }) 18 | } 19 | } 20 | 21 | module.exports = userMiddleware; -------------------------------------------------------------------------------- /week-2/02-nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "02-nodejs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "test-fileServer": "./node_modules/jest/bin/jest.js ./tests/fileServer.test.js", 9 | "test-todoServer": "./node_modules/jest/bin/jest.js ./tests/todoServer.test.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "jest": "^29.5.0", 16 | "supertest": "^6.3.3" 17 | }, 18 | "jest": { 19 | "testTimeout": 10000 20 | }, 21 | "dependencies": { 22 | "express": "^4.18.2", 23 | "uuid": "^9.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /week-6/3-use-ref/src/components/Assignment2.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useCallback } from 'react'; 2 | 3 | // Create a component that tracks and displays the number of times it has been rendered. Use useRef to create a variable that persists across renders without causing additional renders when it changes. 4 | 5 | export function Assignment2() { 6 | const [, forceRender] = useState(0); 7 | 8 | const handleReRender = () => { 9 | // Update state to force re-render 10 | forceRender(Math.random()); 11 | }; 12 | 13 | return ( 14 |
15 |

This component has rendered {0} times.

16 | 17 |
18 | ); 19 | }; -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/routes/user.js: -------------------------------------------------------------------------------- 1 | const { Router } = require("express"); 2 | const router = Router(); 3 | const userMiddleware = require("../middleware/user"); 4 | 5 | // User Routes 6 | router.post('/signup', (req, res) => { 7 | // Implement user signup logic 8 | }); 9 | 10 | router.post('/signin', (req, res) => { 11 | // Implement admin signup logic 12 | }); 13 | 14 | router.get('/courses', (req, res) => { 15 | // Implement listing all courses logic 16 | }); 17 | 18 | router.post('/courses/:courseId', userMiddleware, (req, res) => { 19 | // Implement course purchase logic 20 | }); 21 | 22 | router.get('/purchasedCourses', userMiddleware, (req, res) => { 23 | // Implement fetching purchased courses logic 24 | }); 25 | 26 | module.exports = router -------------------------------------------------------------------------------- /week-5/level-1/README.md: -------------------------------------------------------------------------------- 1 | You have to create a simple React App which has a reusable Card Component which has the following 2 | - Ability to pass in props to the Component 3 | - The Card must show a person's 4 | - Name 5 | - A short description 6 | - LinkedIn, Twitter and other Social Media Handle buttons 7 | - Interests Section 8 | - You can assume that this is kind of an e-business card and feel free to put in your creativity 9 | - Additional & Slightly advanced: 10 | - Create a page where you can add these kind of Cards by taking input from the user 11 | - Create a backend server where these cards get stored in a DB and can handle basic CRUD operations 12 | - Give the feature to perform CRUD operations from the frontend (Can be restricted to the admin only as well) -------------------------------------------------------------------------------- /week-6/solutions/3/components/Assignment1.jsx: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useEffect } from "react"; 3 | 4 | // Create a component with a text input field and a button. When the component mounts or the button is clicked, automatically focus the text input field using useRef. 5 | 6 | export function Assignment1() { 7 | const inputRef = useRef(); 8 | 9 | useEffect(() => { 10 | inputRef.current.focus() 11 | }, [inputRef]); 12 | 13 | const handleButtonClick = () => { 14 | inputRef.current.focus() 15 | }; 16 | 17 | return ( 18 |
19 | 20 | 21 |
22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /week-6/1-use-memo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hooks-assignments", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "^18.2.43", 18 | "@types/react-dom": "^18.2.17", 19 | "@vitejs/plugin-react": "^4.2.1", 20 | "eslint": "^8.55.0", 21 | "eslint-plugin-react": "^7.33.2", 22 | "eslint-plugin-react-hooks": "^4.6.0", 23 | "eslint-plugin-react-refresh": "^0.4.5", 24 | "vite": "^5.0.8" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /week-6/3-use-ref/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hooks-assignments", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "^18.2.43", 18 | "@types/react-dom": "^18.2.17", 19 | "@vitejs/plugin-react": "^4.2.1", 20 | "eslint": "^8.55.0", 21 | "eslint-plugin-react": "^7.33.2", 22 | "eslint-plugin-react-hooks": "^4.6.0", 23 | "eslint-plugin-react-refresh": "^0.4.5", 24 | "vite": "^5.0.8" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /week-6/2-use-callback/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hooks-assignments", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "^18.2.43", 18 | "@types/react-dom": "^18.2.17", 19 | "@vitejs/plugin-react": "^4.2.1", 20 | "eslint": "^8.55.0", 21 | "eslint-plugin-react": "^7.33.2", 22 | "eslint-plugin-react-hooks": "^4.6.0", 23 | "eslint-plugin-react-refresh": "^0.4.5", 24 | "vite": "^5.0.8" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /week-3/03-mongo/solution/middleware/user.js: -------------------------------------------------------------------------------- 1 | const { User } = require("../db"); 2 | 3 | function userMiddleware(req, res, next) { 4 | // Implement admin auth logic 5 | // You need to check the headers and validate the admin from the admin DB. Check readme for the exact headers to be expected 6 | const username = req.headers.username; // harkirat@gmail.com 7 | const password = req.headers.password; /// 123456 8 | 9 | User.findOne({ 10 | username: username, 11 | password: password 12 | }) 13 | .then(function(value) { 14 | if (value) { 15 | next(); 16 | } else { 17 | res.status(403).json({ 18 | msg: "User doesnt exist" 19 | }) 20 | } 21 | }) 22 | } 23 | 24 | module.exports = userMiddleware; -------------------------------------------------------------------------------- /01-js/medium/palindrome.js: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a function `isPalindrome` which takes a string as argument and returns true/false as its result. 3 | Note: the input string is case-insensitive which means 'Nan' is a palindrom as 'N' and 'n' are considered case-insensitive. 4 | */ 5 | 6 | function isPalindrome(str) { 7 | str = str.toLowerCase(); 8 | let i = 0, j = str.length - 1; 9 | while (i < j) { 10 | if (str.charAt(i) == '' || !(/[a-zA-Z]$/.test(str.charAt(i)))) { 11 | i++; 12 | } else if (str.charAt(j) == '' || !(/[a-zA-Z]$/.test(str.charAt(j)))) { 13 | j--; 14 | } else { 15 | if (str.charAt(i) !== str.charAt(j)) { 16 | return false; 17 | } 18 | i++; 19 | j--; 20 | } 21 | } 22 | return true; 23 | } 24 | 25 | module.exports = isPalindrome; 26 | -------------------------------------------------------------------------------- /week-3/01-middlewares/01-requestcount.js: -------------------------------------------------------------------------------- 1 | const request = require('supertest'); 2 | const assert = require('assert'); 3 | const express = require('express'); 4 | 5 | const app = express(); 6 | let requestCount = 0; 7 | 8 | // You have been given an express server which has a few endpoints. 9 | // Your task is to create a global middleware (app.use) which will 10 | // maintain a count of the number of requests made to the server in the global 11 | // requestCount variable 12 | 13 | app.get('/user', function(req, res) { 14 | res.status(200).json({ name: 'john' }); 15 | }); 16 | 17 | app.post('/user', function(req, res) { 18 | res.status(200).json({ msg: 'created dummy user' }); 19 | }); 20 | 21 | app.get('/requestCount', function(req, res) { 22 | res.status(200).json({ requestCount }); 23 | }); 24 | 25 | module.exports = app; -------------------------------------------------------------------------------- /week-6/solutions/3/components/Assignment2.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useCallback } from 'react'; 2 | import { useRef } from 'react'; 3 | 4 | // Create a component that tracks and displays the number of times it has been rendered. 5 | 6 | export function Assignment2() { 7 | const [count, setCount] = useState(0); 8 | 9 | const numberOfTimesReRendered = useRef(0); 10 | 11 | const handleReRender = () => { 12 | // Update state to force re-render 13 | setCount(count + 1); 14 | }; 15 | 16 | numberOfTimesReRendered.current = numberOfTimesReRendered.current + 1; 17 | 18 | return ( 19 |
20 |

This component has rendered {numberOfTimesReRendered.current} times.

21 | 22 |
23 | ); 24 | }; -------------------------------------------------------------------------------- /01-js/README.md: -------------------------------------------------------------------------------- 1 | ## JavaScript Assignments 2 | 3 | You are provided empty JavaScript files (or having function signatures) in this directory. 4 | You have to follow the instructions given in each file and write the code in the same file to complete the assignment. 5 | 6 | ### Assignments 7 | Feel free to start doing these in any order you like. 8 | 1. Easy 9 | 2. Medium 10 | 3. Hard 11 | 12 | ## Testing 13 | 1. Follow the comment above each problem to run test for that problem 14 | 3. To tests for all the problems of this week run ```npx jest ./tests/``` 15 | 16 | #### Development Setup 17 | 1. If you have Node.js locally, you should run these on your machine 18 | 2. If you don't, you can copy these over to repl.it and run it there. Tests wont be automated there so you will have to make use judgement to ensure if your code is correct 19 | -------------------------------------------------------------------------------- /01-js/medium/countVowels.js: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a function `countVowels` that takes a string as an argument and returns the number of vowels in the string. 3 | Note: Consider both uppercase and lowercase vowels ('a', 'e', 'i', 'o', 'u'). 4 | 5 | Once you've implemented the logic, test your code by running 6 | */ 7 | 8 | function countVowels(str) { 9 | // Your code here 10 | let count = 0; 11 | str = str.toLowerCase(); 12 | let hashSet = new Set(); 13 | 14 | // Adding elements to the HashSet 15 | hashSet.add("a"); 16 | hashSet.add("e"); 17 | hashSet.add("i"); 18 | hashSet.add("o"); 19 | hashSet.add("u"); 20 | 21 | for (let index = 0; index < str.length; index++) { 22 | if (hashSet.has(str.charAt(index))) { 23 | count++; 24 | } 25 | } 26 | 27 | return count; 28 | } 29 | 30 | module.exports = countVowels; -------------------------------------------------------------------------------- /week-3/03-mongo/solution/middleware/admin.js: -------------------------------------------------------------------------------- 1 | const { Admin } = require("../db"); 2 | 3 | // Middleware for handling auth 4 | function adminMiddleware(req, res, next) { 5 | // Implement admin auth logic 6 | // You need to check the headers and validate the admin from the admin DB. Check readme for the exact headers to be expected 7 | const username = req.headers.username; // harkirat@gmail.com 8 | const password = req.headers.password; /// 123456 9 | 10 | Admin.findOne({ 11 | username: username, 12 | password: password 13 | }) 14 | .then(function(value) { 15 | if (value) { 16 | next(); 17 | } else { 18 | res.status(403).json({ 19 | msg: "Admin doesnt exist" 20 | }) 21 | } 22 | }) 23 | } 24 | 25 | module.exports = adminMiddleware; -------------------------------------------------------------------------------- /week-3/solutions/01-requestcount.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const app = express(); 4 | let requestCount = 0; 5 | 6 | // You have been given an express server which has a few endpoints. 7 | // Your task is to create a global middleware (app.use) which will 8 | // maintain a count of the number of requests made to the server in the global 9 | // requestCount variable 10 | 11 | app.use(function(req, res, next) { 12 | requestCount = requestCount + 1; 13 | next(); 14 | }); 15 | 16 | app.get('/user', function(req, res) { 17 | res.status(200).json({ name: 'john' }); 18 | }); 19 | 20 | app.post('/user', function(req, res) { 21 | res.status(200).json({ msg: 'created dummy user' }); 22 | }); 23 | 24 | app.get('/requestCount', function(req, res) { 25 | res.status(200).json({ requestCount }); 26 | }); 27 | 28 | module.exports = app; -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/solution/middleware/admin.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | const {JWT_SECRET} = require("../config"); 3 | 4 | // Middleware for handling auth 5 | function adminMiddleware(req, res, next) { 6 | const token = req.headers.authorization; // bearer token 7 | const words = token.split(" "); // ["Bearer", "token"] 8 | const jwtToken = words[1]; // token 9 | try { 10 | const decodedValue = jwt.verify(jwtToken, JWT_SECRET); 11 | if (decodedValue.username) { 12 | next(); 13 | } else { 14 | res.status(403).json({ 15 | msg: "You are not authenticated" 16 | }) 17 | } 18 | } catch(e) { 19 | res.json({ 20 | msg: "Incorrect inputs" 21 | }) 22 | } 23 | 24 | } 25 | 26 | module.exports = adminMiddleware; -------------------------------------------------------------------------------- /week-6/1-use-memo/src/components/Assignment1.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | // In this assignment, your task is to create a component that performs an expensive calculation (finding the factorial) based on a user input. 4 | // Use useMemo to ensure that the calculation is only recomputed when the input changes, not on every render. 5 | 6 | export function Assignment1() { 7 | const [input, setInput] = useState(0); 8 | // Your solution starts here 9 | const expensiveValue = 0; 10 | // Your solution ends here 11 | 12 | return ( 13 |
14 | setInput(Number(e.target.value))} 18 | /> 19 |

Calculated Value: {expensiveValue}

20 |
21 | ); 22 | } -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/solution/routes/user.js: -------------------------------------------------------------------------------- 1 | const { Router } = require("express"); 2 | const router = Router(); 3 | const userMiddleware = require("../middleware/user"); 4 | 5 | // User Routes 6 | router.post('/signup', (req, res) => { 7 | // Implement user signup logic 8 | }); 9 | 10 | router.post('/signin', (req, res) => { 11 | // Implement admin signup logic 12 | }); 13 | 14 | router.get('/courses', (req, res) => { 15 | // Implement listing all courses logic 16 | }); 17 | 18 | router.post('/courses/:courseId', userMiddleware, (req, res) => { 19 | // Implement course purchase logic 20 | const username = req.username; 21 | console.log(username); 22 | 23 | }); 24 | 25 | router.get('/purchasedCourses', userMiddleware, (req, res) => { 26 | // Implement fetching purchased courses logic 27 | }); 28 | 29 | module.exports = router -------------------------------------------------------------------------------- /week-2/01-async-js/tests/4-promise-chain.test.js: -------------------------------------------------------------------------------- 1 | const calculateTime = require("../hard (promises)/4-promise-chain"); 2 | 3 | describe("calculateTime function", () => { 4 | test("calculates time 1", async () => { 5 | const difference = await calculateTime(1, 2, 3); 6 | expect(difference).toBeGreaterThanOrEqual(6000); 7 | expect(difference).toBeLessThan(7000); 8 | }, 7000); 9 | 10 | test("calculates time 2", async () => { 11 | const difference = await calculateTime(10, 1, 1); 12 | expect(difference).toBeGreaterThanOrEqual(12000); 13 | expect(difference).toBeLessThan(13000); 14 | }, 14000); 15 | 16 | test("calculates time for zero seconds", async () => { 17 | const difference = await calculateTime(0, 0, 0); 18 | expect(difference).toBeGreaterThanOrEqual(0); 19 | expect(difference).toBeLessThan(100); 20 | }, 100); 21 | }); 22 | -------------------------------------------------------------------------------- /week-1/offline-class-1/level-2/05-Object.js: -------------------------------------------------------------------------------- 1 | // Object Methods Explanation 2 | function objectMethods(obj) { 3 | console.log("Original Object:", obj); 4 | 5 | let keys = Object.keys(obj); 6 | console.log("After Object.keys():", keys); 7 | 8 | let values = Object.values(obj); 9 | console.log("After Object.values():", values); 10 | 11 | let entries = Object.entries(obj); 12 | console.log("After Object.entries():", entries); 13 | 14 | let hasProp = obj.hasOwnProperty("property"); 15 | console.log("After hasOwnProperty():", hasProp); 16 | 17 | let newObj = Object.assign({}, obj, { newProperty: "newValue" }); 18 | console.log("After Object.assign():", newObj); 19 | 20 | 21 | } 22 | 23 | // Example Usage for Object Methods 24 | const sampleObject = { 25 | key1: "value1", 26 | key2: "value2", 27 | key3: "value3", 28 | }; 29 | 30 | objectMethods(sampleObject); 31 | -------------------------------------------------------------------------------- /week-3/01-middlewares/03-errorcount.js: -------------------------------------------------------------------------------- 1 | const request = require('supertest'); 2 | const assert = require('assert'); 3 | const express = require('express'); 4 | 5 | const app = express(); 6 | let errorCount = 0; 7 | 8 | // You have been given an express server which has a few endpoints. 9 | // Your task is to 10 | // 1. Ensure that if there is ever an exception, the end user sees a status code of 404 11 | // 2. Maintain the errorCount variable whose value should go up every time there is an exception in any endpoint 12 | 13 | app.get('/user', function(req, res) { 14 | throw new Error("User not found"); 15 | res.status(200).json({ name: 'john' }); 16 | }); 17 | 18 | app.post('/user', function(req, res) { 19 | res.status(200).json({ msg: 'created dummy user' }); 20 | }); 21 | 22 | app.get('/errorCount', function(req, res) { 23 | res.status(200).json({ errorCount }); 24 | }); 25 | 26 | module.exports = app; -------------------------------------------------------------------------------- /01-js/medium/times.js: -------------------------------------------------------------------------------- 1 | /* 2 | Write a function that calculates the time (in seconds) it takes for the JS code to calculate sum from 1 to n, given n as the input. 3 | Try running it for 4 | 1. Sum from 1-100 5 | 2. Sum from 1-100000 6 | 3. Sum from 1-1000000000 7 | Hint - use Date class exposed in JS 8 | There is no automated test for this one, this is more for you to understand time goes up as computation goes up 9 | */ 10 | 11 | function calculateTime(n) { 12 | let start = performance.now(); 13 | let sum = 0; 14 | for (let index = 1; index <= n; index++) { 15 | sum += index; 16 | } 17 | let end = performance.now(); 18 | return end - start; 19 | } 20 | 21 | console.log("computation time for 100 is : " + calculateTime(100)); 22 | console.log("computation time for 100000 is : " + calculateTime(100000)); 23 | console.log("computation time for 1000000000 is : " + calculateTime(1000000000)); -------------------------------------------------------------------------------- /week-3/01-middlewares/tests/01-requestcount.spec.js: -------------------------------------------------------------------------------- 1 | const app = require("../01-requestcount"); 2 | 3 | const request = require('supertest'); 4 | const assert = require('assert'); 5 | describe('GET /user', function() { 6 | it('One request responds with 1', function(done) { 7 | request(app) 8 | .get('/requestCount') 9 | .then(response => { 10 | expect(response.body.requestCount).toBe(1); 11 | done(); 12 | }) 13 | }); 14 | 15 | it('10 more requests log 12', function(done) { 16 | for (let i = 0; i<10; i++) { 17 | request(app) 18 | .get('/user') 19 | .then(); 20 | } 21 | request(app) 22 | .get('/requestCount') 23 | .then(response => { 24 | expect(response.body.requestCount).toBe(12); 25 | done(); 26 | }) 27 | }); 28 | }); 29 | 30 | -------------------------------------------------------------------------------- /week-4/README.md: -------------------------------------------------------------------------------- 1 | You have been given the code of a purely frontend TODO app 2 | You have to fill in the following functions - 3 | - addTodoToDom 4 | - removeTodoFromDom 5 | - updateTodoInDom 6 | - updateState 7 | 8 | These 4 functions comprise of what it means to create a library like React. 9 | The goal is the following - 10 | 1. Any time the updateState function is called with a new state, the updateState function calculates the diff between newTodos and oldTodos and call `addTodoToDom`, `removeTodoFromDom` or `updateState` based on the calculated diff. 11 | 2. They id of a todo uniquely identifies it. If the title of a todo with the same id changes in two iterations, updateTodoInDom should be called for it. 12 | 3. The structure of the state variable looks something like this - 13 | ```js 14 | const todos = [{ 15 | title: "Go to gym", 16 | description: "Go to gym from 7-8PM", 17 | id: 1 18 | }] 19 | ``` -------------------------------------------------------------------------------- /week-1/offline-class-1/level-2/04-Math.js: -------------------------------------------------------------------------------- 1 | function mathMethods(value) { 2 | console.log("Original Value:", value); 3 | 4 | let rounded = Math.round(value); 5 | console.log("After round():", rounded); 6 | 7 | let ceiling = Math.ceil(value); 8 | console.log("After ceil():", ceiling); 9 | 10 | let flooring = Math.floor(value); 11 | console.log("After floor():", flooring); 12 | 13 | let randomValue = Math.random(); 14 | console.log("After random():", randomValue); 15 | 16 | let maxValue = Math.max(5, 10, 15); 17 | console.log("After max():", maxValue); 18 | 19 | let minValue = Math.min(5, 10, 15); 20 | console.log("After min():", minValue); 21 | 22 | let powerOfTwo = Math.pow(value, 2); 23 | console.log("After pow():", powerOfTwo); 24 | 25 | let squareRoot = Math.sqrt(value); 26 | console.log("After sqrt():", squareRoot); 27 | } 28 | 29 | // Example Usage for Math Methods 30 | mathMethods(4.56); 31 | mathMethods(9); 32 | mathMethods(25); 33 | -------------------------------------------------------------------------------- /week-6/1-use-memo/src/components/Assignment3.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useMemo } from 'react'; 2 | // You have been given a list of items you shopped from the grocery store 3 | // You need to calculate the total amount of money you spent 4 | 5 | export const Assignment3 = () => { 6 | const [items, setItems] = useState([ 7 | { name: 'Chocolates', value: 10 }, 8 | { name: 'Chips', value: 20 }, 9 | { name: 'Onion', value: 30 }, 10 | { name: 'Tomato', value: 30 }, 11 | // Add more items as needed 12 | ]); 13 | 14 | // Your code starts here 15 | const totalValue = 0; 16 | // Your code ends here 17 | return ( 18 |
19 |
    20 | {items.map((item, index) => ( 21 |
  • {item.name} - Price: ${item.value}
  • 22 | ))} 23 |
24 |

Total Value: {totalValue}

25 |
26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /week-3/01-middlewares/02-ratelimitter.js: -------------------------------------------------------------------------------- 1 | const request = require('supertest'); 2 | const assert = require('assert'); 3 | const express = require('express'); 4 | const app = express(); 5 | // You have been given an express server which has a few endpoints. 6 | // Your task is to create a global middleware (app.use) which will 7 | // rate limit the requests from a user to only 5 request per second 8 | // If a user sends more than 5 requests in a single second, the server 9 | // should block them with a 404. 10 | // User will be sending in their user id in the header as 'user-id' 11 | // You have been given a numberOfRequestsForUser object to start off with which 12 | // clears every one second 13 | 14 | let numberOfRequestsForUser = {}; 15 | setInterval(() => { 16 | numberOfRequestsForUser = {}; 17 | }, 1000) 18 | 19 | app.get('/user', function(req, res) { 20 | res.status(200).json({ name: 'john' }); 21 | }); 22 | 23 | app.post('/user', function(req, res) { 24 | res.status(200).json({ msg: 'created dummy user' }); 25 | }); 26 | 27 | module.exports = app; -------------------------------------------------------------------------------- /week-6/2-use-callback/src/components/Assignment1.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | // Create a counter component with increment and decrement functions. Pass these functions to a child component which has buttons to perform the increment and decrement actions. Use useCallback to ensure that these functions are not recreated on every render. 4 | 5 | export function Assignment1() { 6 | const [count, setCount] = useState(0); 7 | 8 | // Your code starts here 9 | function handleIncrement() { 10 | 11 | } 12 | 13 | function handleDecrement() { 14 | 15 | } 16 | // Your code ends here 17 | 18 | return ( 19 |
20 |

Count: {count}

21 | 22 |
23 | ); 24 | }; 25 | 26 | const CounterButtons = ({ onIncrement, onDecrement }) => ( 27 |
28 | 29 | 30 |
31 | ); 32 | -------------------------------------------------------------------------------- /week-6/solutions/1/components/Assignment1.jsx: -------------------------------------------------------------------------------- 1 | import { useMemo, useState } from "react"; 2 | 3 | // In this assignment, your task is to create a component that performs an expensive calculation (finding the factorial) based on a user input. 4 | // Use useMemo to ensure that the calculation is only recomputed when the input changes, not on every render. 5 | 6 | export function Assignment1() { 7 | const [input, setInput] = useState(0); 8 | 9 | const expensiveValue = useMemo(() => { 10 | // Your solution starts here 11 | let value = 1; 12 | for (let i = 1; i <= input; i++) { 13 | value = value * i; 14 | } 15 | return value; 16 | }, [input]); 17 | 18 | // Your solution ends here 19 | 20 | return ( 21 |
22 | setInput(Number(e.target.value))} 26 | /> 27 |

Calculated Value: {expensiveValue}

28 |
29 | ); 30 | } -------------------------------------------------------------------------------- /week-3/solutions/03-errorcount.js: -------------------------------------------------------------------------------- 1 | const request = require('supertest'); 2 | const assert = require('assert'); 3 | const express = require('express'); 4 | 5 | const app = express(); 6 | let errorCount = 0; 7 | 8 | app.get('/user', function(req, res) { 9 | throw new Error("some error"); 10 | // 500 11 | res.status(200).json({ name: 'john' }); 12 | }); 13 | 14 | app.post('/user', function(req, res) { 15 | res.status(200).json({ msg: 'created dummy user' }); 16 | }); 17 | 18 | app.get('/errorCount', function(req, res) { 19 | res.status(200).json({ errorCount }); 20 | }); 21 | 22 | 23 | // You have been given an express server which has a few endpoints. 24 | // Your task is to 25 | // 1. Ensure that if there is ever an exception, the end user sees a status code of 404 26 | // 2. Maintain the errorCount variable whose value should go up every time there is an exception in any endpoint 27 | 28 | // error handling middleware 29 | app.use(function(err, req, res, next) { 30 | res.status(404).send({}) 31 | errorCount = errorCount + 1; 32 | }) 33 | 34 | module.exports = app; -------------------------------------------------------------------------------- /01-js/tests/findLargestElement.test.js: -------------------------------------------------------------------------------- 1 | const findLargestElement = require('../easy/findLargestElement'); 2 | 3 | describe('findLargestElement', () => { 4 | test('returns the largest element in the array', () => { 5 | expect(findLargestElement([3, 7, 2, 9, 1])).toBe(9); 6 | expect(findLargestElement([15, 27, 8, 12])).toBe(27); 7 | expect(findLargestElement([-5, -10, -2, -8])).toBe(-2); 8 | expect(findLargestElement([0, 0, 0, 0])).toBe(0); 9 | }); 10 | 11 | test('works with arrays containing negative numbers', () => { 12 | expect(findLargestElement([-3, -7, -2, -9, -1])).toBe(-1); 13 | expect(findLargestElement([-15, -27, -8, -12])).toBe(-8); 14 | }); 15 | 16 | test('works with arrays containing decimals', () => { 17 | expect(findLargestElement([3.5, 7.2, 2.1, 9.8, 1.9])).toBe(9.8); 18 | expect(findLargestElement([-3.5, -7.2, -2.1, -9.8, -1.9])).toBe(-1.9); 19 | }); 20 | 21 | test('returns undefined for an empty array', () => { 22 | expect(findLargestElement([])).toBeUndefined(); 23 | }); 24 | }); -------------------------------------------------------------------------------- /week-2/01-async-js/hard (promises)/3-promise-all.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Write 3 different functions that return promises that resolve after t1, t2, and t3 seconds respectively. 3 | * Write a function that uses the 3 functions to wait for all 3 promises to resolve using Promise.all, 4 | * Return a promise.all which return the time in milliseconds it takes to complete the entire operation. 5 | */ 6 | 7 | function wait1(t) { 8 | return new Promise((resolve, reject) => { 9 | setTimeout(() => { resolve() }, t * 1000) 10 | }) 11 | } 12 | 13 | function wait2(t) { 14 | return new Promise((resolve, reject) => { 15 | setTimeout(() => { resolve() }, t * 1000) 16 | }) 17 | } 18 | 19 | function wait3(t) { 20 | return new Promise((resolve, reject) => { 21 | setTimeout(() => { resolve() }, t * 1000) 22 | }) 23 | } 24 | 25 | async function calculateTime(t1, t2, t3) { 26 | let time = new Date().getTime(); 27 | await Promise.all([wait1(t1), wait2(t2), wait3(t3)]); 28 | return (new Date().getTime() - time); 29 | } 30 | 31 | module.exports = calculateTime; 32 | -------------------------------------------------------------------------------- /week-2/01-async-js/tests/3-promise-all.test.js: -------------------------------------------------------------------------------- 1 | const calculateTime = require("../hard (promises)/3-promise-all"); 2 | 3 | describe("calculateTime function", () => { 4 | test("calculates time 1", async () => { 5 | const difference = await calculateTime(1, 2, 3); 6 | expect(difference).toBeGreaterThanOrEqual(3000); 7 | expect(difference).toBeLessThan(4000); 8 | }, 4000); 9 | 10 | test("calculates time 2", async () => { 11 | const difference = await calculateTime(4, 5, 7); 12 | expect(difference).toBeGreaterThanOrEqual(7000); 13 | expect(difference).toBeLessThan(8000); 14 | }, 8000); 15 | 16 | test("calculates time 3", async () => { 17 | const difference = await calculateTime(10, 1, 1); 18 | expect(difference).toBeGreaterThanOrEqual(10000); 19 | expect(difference).toBeLessThan(11000); 20 | }, 11000); 21 | 22 | test("calculates time for zero seconds", async () => { 23 | const difference = await calculateTime(0, 0, 0); 24 | expect(difference).toBeGreaterThanOrEqual(0); 25 | expect(difference).toBeLessThan(1000); 26 | }, 1000); 27 | }); 28 | -------------------------------------------------------------------------------- /week-3/03-mongo/solution/db/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | // Connect to MongoDB 4 | mongoose.connect('mongodb+srv://kirags123:8qPEa8KTKBEh2bss@cluster0.f3qlbuo.mongodb.net/course_selling_app'); 5 | 6 | // Define schemas 7 | const AdminSchema = new mongoose.Schema({ 8 | // Schema definition here 9 | username: String, 10 | password: String 11 | }); 12 | 13 | const UserSchema = new mongoose.Schema({ 14 | // Schema definition here 15 | username: String, 16 | password: String, 17 | purchasedCourses: [{ 18 | type: mongoose.Schema.Types.ObjectId, 19 | ref: 'Course' 20 | }] 21 | }); 22 | 23 | const CourseSchema = new mongoose.Schema({ 24 | // Schema definition here 25 | title: String, 26 | description: String, 27 | imageLink: String, 28 | price: Number 29 | }); 30 | 31 | const Admin = mongoose.model('Admin', AdminSchema); 32 | const User = mongoose.model('User', UserSchema); 33 | const Course = mongoose.model('Course', CourseSchema); 34 | 35 | module.exports = { 36 | Admin, 37 | User, 38 | Course 39 | } 40 | -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/solution/db/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | // Connect to MongoDB 4 | mongoose.connect('mongodb+srv://kirags123:8qPEa8KTKBEh2bss@cluster0.f3qlbuo.mongodb.net/course_selling_app2'); 5 | 6 | // Define schemas 7 | const AdminSchema = new mongoose.Schema({ 8 | // Schema definition here 9 | username: String, 10 | password: String 11 | }); 12 | 13 | const UserSchema = new mongoose.Schema({ 14 | // Schema definition here 15 | username: String, 16 | password: String, 17 | purchasedCourses: [{ 18 | type: mongoose.Schema.Types.ObjectId, 19 | ref: 'Course' 20 | }] 21 | }); 22 | 23 | const CourseSchema = new mongoose.Schema({ 24 | // Schema definition here 25 | title: String, 26 | description: String, 27 | imageLink: String, 28 | price: Number 29 | }); 30 | 31 | const Admin = mongoose.model('Admin', AdminSchema); 32 | const User = mongoose.model('User', UserSchema); 33 | const Course = mongoose.model('Course', CourseSchema); 34 | 35 | module.exports = { 36 | Admin, 37 | User, 38 | Course 39 | } 40 | -------------------------------------------------------------------------------- /week-3/README.md: -------------------------------------------------------------------------------- 1 | This week is divided into three parts for assignments - 2 | 3 | ## Middlewares 4 | - You have to create a few standard middlewares for your application. 5 | - You have to create a middleware for logging the number of requests on a server 6 | - You have to create a middleware for rate limiting a users request based on their username passed in the header 7 | - You have to create a middleware for logging the number of errors on a server 8 | - To test, go to the 01-middlewares folder and run `npx jest ./tests` 9 | 10 | ## JWTs 11 | - Write a function that takes in a username and password and returns a JWT token with the username encoded. Should return null if the username is not a valid email or if the password is less than 6 characters. Try using the zod library here 12 | - Write a function that takes a jwt as input and returns true if the jwt can be DECODED (not verified). Return false otherwise 13 | - Write a function that takes a jwt as input and returns true if the jwt can be VERIFIED. Return false otherewise 14 | - To test, go to the 02-jwt folder and run `npx jest ./tests` 15 | 16 | ## Databases -------------------------------------------------------------------------------- /01-js/easy/expenditure-analysis.js: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a function `calculateTotalSpentByCategory` which takes a list of transactions as parameter 3 | and return a list of objects where each object is unique category-wise and has total price spent as its value. 4 | transactions is an array where each 5 | Transaction - an object like 6 | { 7 | id: 1, 8 | timestamp: 1656076800000, 9 | price: 10, 10 | category: 'Food', 11 | itemName: 'Pizza', 12 | } 13 | Output - [{ category: 'Food', totalSpent: 10 }] // Can have multiple categories, only one example is mentioned here 14 | */ 15 | 16 | function calculateTotalSpentByCategory(transactions) { 17 | let obj = []; 18 | for (let i = 0; i < transactions.length; i++) { 19 | const searchCategory = obj.find(item => item.category == transactions[i].category); 20 | if (searchCategory) { 21 | searchCategory.totalSpent += transactions[i].price; 22 | } else { 23 | obj.push({ category: transactions[i].category, totalSpent: transactions[i].price }) 24 | } 25 | } 26 | return obj; 27 | } 28 | 29 | module.exports = calculateTotalSpentByCategory; 30 | -------------------------------------------------------------------------------- /week-2/02-nodejs/fileServer.js: -------------------------------------------------------------------------------- 1 | /** 2 | You need to create an express HTTP server in Node.js which will handle the logic of a file server. 3 | - Use built in Node.js `fs` module 4 | The expected API endpoints are defined below, 5 | 1. GET /files - Returns a list of files present in `./files/` directory 6 | Response: 200 OK with an array of file names in JSON format. 7 | Example: GET http://localhost:3000/files 8 | 2. GET /file/:filename - Returns content of given file by name 9 | Description: Use the filename from the request path parameter to read the file from `./files/` directory 10 | Response: 200 OK with the file content as the response body if found, or 404 Not Found if not found. Should return `File not found` as text if file is not found 11 | Example: GET http://localhost:3000/file/example.txt 12 | - For any other route not defined in the server return 404 13 | Testing the server - run `npm run test-fileServer` command in terminal 14 | */ 15 | const express = require('express'); 16 | const fs = require('fs'); 17 | const path = require('path'); 18 | const app = express(); 19 | 20 | 21 | module.exports = app; -------------------------------------------------------------------------------- /week-1/offline-class-1/level-2/02-Date.js: -------------------------------------------------------------------------------- 1 | function dateMethods() { 2 | const currentDate = new Date(); 3 | console.log("Current Date:", currentDate); 4 | 5 | // Getting various components of the date 6 | console.log("Date:", currentDate.getDate()); 7 | console.log("Month:", currentDate.getMonth() + 1); // Months are zero-indexed, so adding 1 8 | console.log("Year:", currentDate.getFullYear()); 9 | console.log("Hours:", currentDate.getHours()); 10 | console.log("Minutes:", currentDate.getMinutes()); 11 | console.log("Seconds:", currentDate.getSeconds()); 12 | 13 | // Setting components of the date 14 | currentDate.setFullYear(2022); 15 | console.log("After setFullYear:", currentDate); 16 | 17 | currentDate.setMonth(5); // Setting month to June (zero-indexed) 18 | console.log("After setMonth:", currentDate); 19 | 20 | // Getting and setting time in milliseconds since 1970 21 | console.log("Time in milliseconds since 1970:", currentDate.getTime()); 22 | 23 | const newDate = new Date(2023, 8, 15); // Creating a new date 24 | console.log("New Date:", newDate); 25 | } 26 | 27 | // Example Usage for Date Methods 28 | dateMethods(); 29 | -------------------------------------------------------------------------------- /01-js/hard/todo-list.js: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a class `Todo` having below methods 3 | - add(todo): adds todo to list of todos 4 | - remove(indexOfTodo): remove todo from list of todos 5 | - update(index, updatedTodo): update todo at given index 6 | - getAll: returns all todos 7 | - get(indexOfTodo): returns todo at given index 8 | - clear: deletes all todos 9 | 10 | Once you've implemented the logic, test your code by running 11 | */ 12 | 13 | class Todo { 14 | constructor() { 15 | this.list = []; 16 | } 17 | 18 | add(todo) { 19 | this.list.push(todo) 20 | } 21 | 22 | remove(indexOfTodo) { 23 | this.list.splice(indexOfTodo, 1); 24 | } 25 | 26 | update(index, updatedTodo) { 27 | if (index >= this.list.length) { 28 | return; 29 | } 30 | this.list[index] = updatedTodo; 31 | } 32 | 33 | getAll() { 34 | return this.list; 35 | } 36 | 37 | get(indexOfTodo) { 38 | if (indexOfTodo >= this.list.length) { 39 | return null; 40 | } 41 | return this.list[indexOfTodo]; 42 | } 43 | 44 | clear() { 45 | this.list = []; 46 | } 47 | 48 | } 49 | 50 | module.exports = Todo; 51 | -------------------------------------------------------------------------------- /week-2/01-async-js/README.md: -------------------------------------------------------------------------------- 1 | ## JavaScript Assignments 2 | 3 | This folder contains assignments related to asynchronous JavaScript. 4 | 5 | ### Assignments 6 | 7 | Recommended order below but feel free to make a mess in any order you like. 8 | 1. Easy 9 | 1. Counter 10 | 2. Counter (no setInterval) 11 | 3. Read from a file 12 | 4. Write to a file 13 | 2. Medium 14 | 1. File cleaner 15 | 2. Clock 16 | 3. Hard 17 | 1. Promisify setTimeout 18 | 2. Sleep completely 19 | 3. Promise all 20 | 4. Promise chain 21 | 22 | #### Development Setup 23 | 1. If you have Node.js locally, you should run these on your machine 24 | 2. If you don't, you can copy these over to repl.it and run it there. 25 | 26 | #### How to Run Tests 27 | 1. Your working directory must be /assignments/week-2/01-async-js 28 | 2. Do npm install 29 | 3. To run tests run `npx jest ./tests/` 30 | for example, `npx jest ./tests/1-promisify-setTimeout.test.js` 31 | 4. If the above does not work for you, to run tests run `npm run ` 32 | for example, `npm run 1-promisify-setTimeout` 33 | 5. To run all tests run `npx jest ./tests/` or `npm run all` -------------------------------------------------------------------------------- /week-3/solutions/02.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const jwtPassword = "secret"; 3 | const zod = require("zod"); 4 | 5 | const emailSchema = zod.string().email(); 6 | const passwordSchema = zod.string().min(6); 7 | 8 | function signJwt(username, password) { 9 | const usernameResponse = emailSchema.safeParse(username); 10 | const passwordResponse = passwordSchema.safeParse(password); 11 | if (!usernameResponse.success || !passwordResponse.success) { 12 | return null; 13 | } 14 | 15 | const signature = jwt.sign({ 16 | username 17 | }, jwtPassword); 18 | 19 | return signature; 20 | } 21 | 22 | function verifyJwt(token) { 23 | let ans = true; 24 | try { 25 | jwt.verify(token, jwtPassword); 26 | } catch(e) { 27 | ans = false; 28 | } 29 | return ans; 30 | } 31 | 32 | function decodeJwt(token) { 33 | // true, false 34 | const decoded = jwt.decode(token); 35 | if (decoded) { 36 | return true; 37 | } else { 38 | return false; 39 | } 40 | } 41 | 42 | module.exports = { 43 | signJwt, 44 | verifyJwt, 45 | decodeJwt, 46 | jwtPassword 47 | } -------------------------------------------------------------------------------- /week-3/01-middlewares/tests/03-errorcount.spec.js: -------------------------------------------------------------------------------- 1 | const app = require("../03-errorcount"); 2 | 3 | const request = require('supertest'); 4 | const assert = require('assert'); 5 | describe('GET /user', function() { 6 | it('Initial request responds with 0', function(done) { 7 | request(app) 8 | .get('/errorCount') 9 | .then(response => { 10 | expect(response.body.errorCount).toBe(0); 11 | done(); 12 | }) 13 | }); 14 | 15 | it('If there is an exception, errCount goes up', function(done) { 16 | for (let i = 0; i<10; i++) { 17 | request(app) 18 | .get('/user') 19 | .then(); 20 | } 21 | request(app) 22 | .get('/errorCount') 23 | .then(response => { 24 | expect(response.body.errorCount).toBe(10); 25 | done(); 26 | }) 27 | }); 28 | 29 | it('Exception endpoint returns a 404', function(done) { 30 | request(app) 31 | .get('/user') 32 | .then(response => { 33 | expect(response.status).toBe(404); 34 | done(); 35 | }) 36 | }); 37 | 38 | }); 39 | 40 | -------------------------------------------------------------------------------- /week-2/01-async-js/hard (promises)/4-promise-chain.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Write 3 different functions that return promises that resolve after t1, t2, and t3 seconds respectively. 3 | * Write a function that sequentially calls all 3 of these functions in order. 4 | * Return a promise chain which return the time in milliseconds it takes to complete the entire operation. 5 | * Compare it with the results from 3-promise-all.js 6 | */ 7 | 8 | function wait1(t) { 9 | return new Promise((resolve, reject) => { 10 | setTimeout(() => { resolve() }, t * 1000) 11 | }) 12 | } 13 | 14 | function wait2(t) { 15 | return new Promise((resolve, reject) => { 16 | setTimeout(() => { resolve() }, t * 1000) 17 | }) 18 | } 19 | 20 | function wait3(t) { 21 | return new Promise((resolve, reject) => { 22 | setTimeout(() => { resolve() }, t * 1000) 23 | }) 24 | } 25 | 26 | function calculateTime(t1, t2, t3) { 27 | const start = new Date().getTime(); 28 | return wait1(t1).then((value) => { 29 | return wait2(t2); 30 | }).then((value) => { 31 | return wait3(t3) 32 | }).then((value) => { 33 | return (new Date().getTime() - start) 34 | }) 35 | } 36 | 37 | module.exports = calculateTime; 38 | -------------------------------------------------------------------------------- /week-6/solutions/1/components/Assignment3.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useMemo } from 'react'; 2 | // You have been given a list of items you shopped from the grocery store 3 | // You need to calculate the total amount of money you spent 4 | 5 | export const Assignment3 = () => { 6 | const [items, setItems] = useState([ 7 | { name: 'Chocolates', value: 10 }, 8 | { name: 'Chips', value: 20 }, 9 | { name: 'Onion', value: 30 }, 10 | { name: 'Tomato', value: 30 }, 11 | { name: 'Tomato', value: 100 }, 12 | // Add more items as needed 13 | ]); 14 | 15 | // Your code starts here 16 | // reducer 17 | const totalValue = useMemo(() => { 18 | let totalValue = 0; 19 | for (let i = 0; i < items.length; i++) { 20 | totalValue = totalValue + items[i].value; 21 | } 22 | return totalValue 23 | }, [items]) 24 | 25 | // Your code ends here 26 | return ( 27 |
28 |
    29 | {items.map((item, index) => ( 30 |
  • {item.name} - Price: ${item.value}
  • 31 | ))} 32 |
33 |

Total Value: {totalValue}

34 |
35 | ); 36 | }; 37 | -------------------------------------------------------------------------------- /01-js/tests/anagram.test.js: -------------------------------------------------------------------------------- 1 | const isAnagram = require('../easy/anagram'); 2 | 3 | describe('isAnagram', () => { 4 | test('returns true for anagrams', () => { 5 | expect(isAnagram('listen', 'silent')).toBe(true); 6 | expect(isAnagram('rail safety', 'fairy tales')).toBe( 7 | true 8 | ); 9 | expect(isAnagram('openai', 'aiopen')).toBe(true); 10 | expect(isAnagram('', '')).toBe(true); 11 | }); 12 | 13 | test('returns false for non-anagrams', () => { 14 | expect(isAnagram('hello', 'world')).toBe(false); 15 | expect(isAnagram('openai', 'open')).toBe(false); 16 | expect(isAnagram('hello', 'lhel')).toBe(false); 17 | expect(isAnagram('working', 'non')).toBe(false); 18 | }); 19 | 20 | test('returns true for anagrams with different casing', () => { 21 | expect(isAnagram('Debit Card', 'Bad Credit')).toBe( 22 | true 23 | ); 24 | expect( 25 | isAnagram('School MASTER', 'The ClassROOM') 26 | ).toBe(true); 27 | }); 28 | 29 | test('returns true for anagrams with special characters', () => { 30 | expect(isAnagram('abc!', '!bac')).toBe(true); 31 | }); 32 | 33 | test('returns false for non-anagrams with special characters', () => { 34 | expect(isAnagram('hello', 'hello!')).toBe(false); 35 | expect(isAnagram('openai!', 'open')).toBe(false); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /week-6/solutions/2/components/Assignment1.jsx: -------------------------------------------------------------------------------- 1 | import { memo, useCallback, useState } from "react"; 2 | 3 | // Create a counter component with increment and decrement functions. Pass these functions to a child component which has buttons to perform the increment and decrement actions. Use useCallback to ensure that these functions are not recreated on every render. 4 | 5 | export function Assignment1() { 6 | const [count, setCount] = useState(0); 7 | 8 | // Your code starts here 9 | const handleIncrement = useCallback(() => { 10 | setCount(function(currentCount) { 11 | return currentCount + 1; 12 | }) 13 | }, []) 14 | 15 | const handleDecrement = useCallback(() => { 16 | setCount(count => { 17 | return count - 1 18 | }); 19 | }, []); 20 | // Your code ends here 21 | 22 | return ( 23 |
24 |

Count: {count}

25 | 26 |
27 | ); 28 | }; 29 | 30 | const CounterButtons = memo(({ onIncrement, onDecrement }) => ( 31 |
32 | 33 | 34 |
35 | )); 36 | -------------------------------------------------------------------------------- /week-6/2-use-callback/src/components/Assignment2.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useCallback } from 'react'; 2 | 3 | // Create a component with a text input field and a button. The goal is to display an alert with the text entered when the button is clicked. Use useCallback to memoize the event handler function that triggers the alert, ensuring it's not recreated on every render. 4 | // Currently we only have inputText as a state variable and hence you might not see the benefits of 5 | // useCallback. We're also not passing it down to another component as a prop which is another reason for you to not see it's benefits immedietely. 6 | 7 | export function Assignment2() { 8 | const [inputText, setInputText] = useState(''); 9 | 10 | // Your code starts here 11 | function showAlert() { 12 | 13 | } 14 | // Your code ends here 15 | 16 | return ( 17 |
18 | setInputText(e.target.value)} 22 | placeholder="Enter some text" 23 | /> 24 | 25 |
26 | ); 27 | }; 28 | 29 | function Alert({showAlert}) { 30 | return 31 | } 32 | 33 | -------------------------------------------------------------------------------- /week-6/solutions/2/components/Assignment2.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useCallback } from 'react'; 2 | 3 | // Create a component with a text input field and a button. The goal is to display an alert with the text entered when the button is clicked. Use useCallback to memoize the event handler function that triggers the alert, ensuring it's not recreated on every render. 4 | // Currently we only have inputText as a state variable and hence you might not see the benefits of 5 | // useCallback. We're also not passing it down to another component as a prop which is another reason for you to not see it's benefits immedietely. 6 | 7 | export function Assignment2() { 8 | const [inputText, setInputText] = useState(''); 9 | 10 | // Your code starts here 11 | const showAlert = useCallback(() => { 12 | alert(inputText); 13 | }, [inputText]) 14 | // Your code ends here 15 | 16 | return ( 17 |
18 | setInputText(e.target.value)} 22 | placeholder="Enter some text" 23 | /> 24 | 25 |
26 | ); 27 | }; 28 | 29 | function Alert({showAlert}) { 30 | return 31 | } 32 | 33 | -------------------------------------------------------------------------------- /week-3/01-middlewares/tests/02-ratelimitter.spec.js: -------------------------------------------------------------------------------- 1 | const app = require("../02-ratelimitter"); 2 | 3 | const request = require('supertest'); 4 | const assert = require('assert'); 5 | describe('GET /user', function () { 6 | const userId = 'testId' 7 | it('One request responds back correctly', function(done) { 8 | request(app) 9 | .get('/user') 10 | .set('user-id', userId) 11 | .then((response) => { 12 | expect(response.status).toBe(200); 13 | done(); 14 | }); 15 | }); 16 | 17 | it('5 or more requests return back a 404', function(done) { 18 | for (let i = 0; i<5; i++) { 19 | request(app).get('/user').set('user-id', userId).then(); 20 | } 21 | request(app) 22 | .get('/user') 23 | .set('user-id', userId) 24 | .then((response) => { 25 | expect(response.status).toBe(404); 26 | done(); 27 | }); 28 | }); 29 | 30 | it('5 or more requests and waiting returns a 200', function(done) { 31 | for (let i = 0; i<5; i++) { 32 | request(app).get('/user').set('user-id', userId).then(); 33 | } 34 | setTimeout(function() { 35 | request(app) 36 | .get('/user') 37 | .set('user-id', userId) 38 | .then((response) => { 39 | expect(response.status).toBe(200); 40 | done(); 41 | }); 42 | }, 2000); 43 | }); 44 | }); 45 | 46 | -------------------------------------------------------------------------------- /week-2/02-nodejs/README.md: -------------------------------------------------------------------------------- 1 | ## Node.js Assignments 2 | In this series of assignments, you are going to create native HTTP servers in Node.js which will handle different kinds of application logics. 3 | 4 | You are provided empty JavaScript files (or having function signatures) in this directory. You have to follow the instructions given in each file and then run automated tests (also mentioned in each file) to check if you have successfully completed the assignment or you still have few more things to learn in it 😜 5 | 6 | ### Assignments 7 | Recommended order of attempting the assignments. 8 | 1. Todo List App 9 | 2. File Server 10 | 11 | #### Important Notes 12 | 1. If you are unable to understand the request/response of any assignment file or whatever the way it is being tested, you can take a look at its respective test file present in `tests/` directory. 13 | 2. Don't try to make any changes to the test files present in the `tests/` directory. 14 | 3. Don't make any changes to the code already present in files including function/method/class signatures and module exports. 15 | 4. To run individual tests - 16 | - npm run test-fileServer 17 | - npm run test-todoServer 18 | 19 | #### Development Setup 20 | 1. Install the dependencies used by running `npm install` command in your terminal. 21 | 2. We used `18.x.y` Node.js version, if anything doesn't work then please consider upgrading your node installation. 22 | -------------------------------------------------------------------------------- /week-3/solutions/02-ratelimitter.js: -------------------------------------------------------------------------------- 1 | 2 | const express = require('express'); 3 | const app = express(); 4 | // You have been given an express server which has a few endpoints. 5 | // Your task is to create a global middleware (app.use) which will 6 | // rate limit the requests from a user to only 5 request per second 7 | // If a user sends more than 5 requests in a single second, the server 8 | // should block them with a 404. 9 | // User will be sending in their user id in the header as 'user-id' 10 | // You have been given a numberOfRequestsForUser object to start off with which 11 | // clears every one second 12 | 13 | let numberOfRequestsForUser = {}; 14 | setInterval(() => { 15 | numberOfRequestsForUser = {}; 16 | }, 1000) 17 | // 18 | app.use(function(req, res, next) { 19 | const userId = req.headers["user-id"]; 20 | 21 | if (numberOfRequestsForUser[userId]) { 22 | numberOfRequestsForUser[userId] = numberOfRequestsForUser[userId] + 1; 23 | if (numberOfRequestsForUser[userId] > 5) { 24 | res.status(404).send("no entry"); 25 | } else { 26 | next(); 27 | } 28 | } else { 29 | numberOfRequestsForUser[userId] = 1; 30 | next(); 31 | } 32 | }) 33 | 34 | 35 | app.get('/user', function(req, res) { 36 | res.status(200).json({ name: 'john' }); 37 | }); 38 | 39 | app.post('/user', function(req, res) { 40 | res.status(200).json({ msg: 'created dummy user' }); 41 | }); 42 | 43 | module.exports = app; -------------------------------------------------------------------------------- /week-6/1-use-memo/src/components/Assignment2.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | 3 | // In this assignment, you will create a component that renders a large list of sentences and includes an input field for filtering these items. 4 | // The goal is to use useMemo to optimize the filtering process, ensuring the list is only re-calculated when necessary (e.g., when the filter criteria changes). 5 | // You will learn something new here, specifically how you have to pass more than one value in the dependency array 6 | 7 | const words = ["hi", "my", "name", "is", "for", "to", "random", "word" ]; 8 | const TOTAL_LINES = 1000; 9 | const ALL_WORDS = []; 10 | for (let i = 0; i < TOTAL_LINES; i++) { 11 | let sentence = ""; 12 | for (let j = 0; j < words.length; j++) { 13 | sentence += (words[Math.floor(words.length * Math.random())]) 14 | sentence += " " 15 | } 16 | ALL_WORDS.push(sentence); 17 | } 18 | 19 | export function Assignment2() { 20 | const [sentences, setSentences] = useState(ALL_WORDS); 21 | const [filter, setFilter] = useState(""); 22 | 23 | const filteredSentences = sentences.filter(x => x.includes(filter)) 24 | 25 | return
26 | { 27 | setFilter(e.target.value) 28 | }}> 29 | {filteredSentences.map(word =>
30 | {word} 31 |
)} 32 |
33 | } -------------------------------------------------------------------------------- /week-6/1-use-memo/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-6/3-use-ref/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /week-6/2-use-callback/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-js/tests/countVowels.test.js: -------------------------------------------------------------------------------- 1 | const countVowels = require('../medium/countVowels'); 2 | 3 | describe('countVowels', () => { 4 | test('returns the correct count for strings with vowels', () => { 5 | expect(countVowels('hello')).toBe(2); 6 | expect(countVowels('programming')).toBe(3); 7 | expect(countVowels('OpenAI')).toBe(4); 8 | }); 9 | 10 | test('returns 0 for strings without vowels', () => { 11 | expect(countVowels('rhythm')).toBe(0); 12 | expect(countVowels('fly')).toBe(0); 13 | expect(countVowels('chatbot')).toBe(2); 14 | }); 15 | 16 | test('returns 0 for an empty string', () => { 17 | expect(countVowels('')).toBe(0); 18 | }); 19 | 20 | test('handles case-insensitivity correctly', () => { 21 | expect(countVowels('EaSiEr')).toBe(4); 22 | expect(countVowels('QUIET')).toBe(3); 23 | expect(countVowels('aEIOU')).toBe(5); 24 | }); 25 | 26 | test('returns the correct count for strings with spaces', () => { 27 | expect(countVowels('the quick brown fox')).toBe(5); 28 | expect(countVowels('a e i o u')).toBe(5); 29 | expect(countVowels('testing spaces')).toBe(4); 30 | }); 31 | 32 | test('returns the correct count for strings with punctuation marks', () => { 33 | expect(countVowels('Hello, world!')).toBe(3); 34 | expect(countVowels('Coding is fun!!!')).toBe(4); 35 | expect(countVowels('Keep smiling, boo.')).toBe(6); 36 | }); 37 | }); -------------------------------------------------------------------------------- /week-6/solutions/1/components/Assignment2.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useMemo, useState } from "react"; 2 | 3 | // In this assignment, you will create a component that renders a large list of sentences and includes an input field for filtering these items. 4 | // The goal is to use useMemo to optimize the filtering process, ensuring the list is only re-calculated when necessary (e.g., when the filter criteria changes). 5 | // You will learn something new here, specifically how you have to pass more than one value in the dependency array 6 | 7 | const words = ["hi", "my", "name", "is", "for", "to", "random", "word" ]; 8 | const TOTAL_LINES = 1000; 9 | const ALL_WORDS = []; 10 | for (let i = 0; i < TOTAL_LINES; i++) { 11 | let sentence = ""; 12 | for (let j = 0; j < words.length; j++) { 13 | sentence += (words[Math.floor(words.length * Math.random())]) 14 | sentence += " " 15 | } 16 | ALL_WORDS.push(sentence); 17 | } 18 | 19 | export function Assignment2() { 20 | const [sentences, setSentences] = useState(ALL_WORDS); 21 | const [filter, setFilter] = useState(""); 22 | 23 | const filteredSentences = useMemo(() => { 24 | return sentences.filter(x => x.includes(filter)); 25 | }, [sentences, filter]) 26 | 27 | return
28 | { 29 | setFilter(e.target.value) 30 | }}> 31 | {filteredSentences.map(word =>
32 | {word} 33 |
)} 34 |
35 | } -------------------------------------------------------------------------------- /week-3/03-mongo/solution/routes/admin.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const adminMiddleware = require("../middleware/admin"); 3 | const { Admin, Course } = require("../db"); 4 | const router = express.Router(); 5 | 6 | router.post('/signup', async (req, res) => { 7 | // Implement admin signup logic 8 | const username = req.body.username; 9 | const password = req.body.password; 10 | 11 | // check if a user with this username already exists 12 | await Admin.create({ 13 | username: username, 14 | password: password 15 | }) 16 | 17 | res.json({ 18 | message: 'Admin created successfully' 19 | }) 20 | 21 | }); 22 | 23 | router.post('/courses', adminMiddleware, async (req, res) => { 24 | // Implement course creation logic 25 | const title = req.body.title; 26 | const description = req.body.description; 27 | const imageLink = req.body.imageLink; 28 | const price = req.body.price; 29 | // zod 30 | const newCourse = await Course.create({ 31 | title, 32 | description, 33 | imageLink, 34 | price 35 | }) 36 | 37 | res.json({ 38 | message: 'Course created successfully', courseId: newCourse._id 39 | }) 40 | }); 41 | 42 | router.get('/courses', adminMiddleware, async (req, res) => { 43 | // Implement fetching all courses logic 44 | const response = await Course.find({}); 45 | 46 | res.json({ 47 | courses: response 48 | }) 49 | 50 | }); 51 | 52 | 53 | module.exports = router; -------------------------------------------------------------------------------- /week-2/01-async-js/tests/1-promisify-setTimeout.test.js: -------------------------------------------------------------------------------- 1 | const wait = require("../hard (promises)/1-promisify-setTimeout"); 2 | 3 | describe("wait function", () => { 4 | test("resolves after 1 second", () => { 5 | const start = Date.now(); 6 | return expect(wait(1)) 7 | .resolves.toBeUndefined() // Wait for 1 second 8 | .then(() => { 9 | const end = Date.now(); 10 | const difference = end - start; 11 | expect(difference).toBeGreaterThanOrEqual(1000); // Expect difference to be at least 1000 ms (1 second) 12 | }); 13 | }, 2000); // Set timeout to 2000 ms (2 seconds) 14 | 15 | test("resolves after 2 seconds", () => { 16 | const start = Date.now(); 17 | return expect(wait(2)) 18 | .resolves.toBeUndefined() // Wait for 2 seconds 19 | .then(() => { 20 | const end = Date.now(); 21 | const difference = end - start; 22 | expect(difference).toBeGreaterThanOrEqual(2000); // Expect difference to be at least 2000 ms (2 seconds) 23 | }); 24 | }, 3000); // Set timeout to 3000 ms (3 seconds) 25 | 26 | test("resolves after 3 seconds", () => { 27 | const start = Date.now(); 28 | return expect(wait(3)) 29 | .resolves.toBeUndefined() // Wait for 3 seconds 30 | .then(() => { 31 | const end = Date.now(); 32 | const difference = end - start; 33 | expect(difference).toBeGreaterThanOrEqual(3000); // Expect difference to be at least 3000 ms (3 seconds) 34 | }); 35 | }, 4000); // Set timeout to 4000 ms (4 seconds) 36 | }); 37 | -------------------------------------------------------------------------------- /week-2/01-async-js/tests/2-sleep-completely.test.js: -------------------------------------------------------------------------------- 1 | const sleep = require("../hard (promises)/2-sleep-completely"); 2 | 3 | describe("sleep function", () => { 4 | test("resolves after 1 second", () => { 5 | const start = Date.now(); 6 | return expect(sleep(1000)) 7 | .resolves.toBeUndefined() // Wait for 1 second 8 | .then(() => { 9 | const end = Date.now(); 10 | const difference = end - start; 11 | expect(difference).toBeGreaterThanOrEqual(1000); // Expect difference to be at least 1000 ms (1 second) 12 | }); 13 | }, 2000); // Set timeout to 2000 ms (2 seconds) 14 | 15 | test("resolves after 2 seconds", () => { 16 | const start = Date.now(); 17 | return expect(sleep(2000)) 18 | .resolves.toBeUndefined() // Wait for 2 seconds 19 | .then(() => { 20 | const end = Date.now(); 21 | const difference = end - start; 22 | expect(difference).toBeGreaterThanOrEqual(2000); // Expect difference to be at least 2000 ms (2 seconds) 23 | }); 24 | }, 3000); // Set timeout to 3000 ms (3 seconds) 25 | 26 | test("resolves after 3 seconds", () => { 27 | const start = Date.now(); 28 | return expect(sleep(3000)) 29 | .resolves.toBeUndefined() // Wait for 3 seconds 30 | .then(() => { 31 | const end = Date.now(); 32 | const difference = end - start; 33 | expect(difference).toBeGreaterThanOrEqual(3000); // Expect difference to be at least 3000 ms (3 seconds) 34 | }); 35 | }, 4000); // Set timeout to 4000 ms (4 seconds) 36 | }); 37 | -------------------------------------------------------------------------------- /week-4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 48 | 49 | 50 | 51 |

52 |

53 | 54 |

55 | 56 |
57 | 58 |
59 | 60 | 61 | -------------------------------------------------------------------------------- /week-3/02-jwt/index.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const jwtPassword = 'secret'; 3 | 4 | 5 | /** 6 | * Generates a JWT for a given username and password. 7 | * 8 | * @param {string} username - The username to be included in the JWT payload. 9 | * Must be a valid email address. 10 | * @param {string} password - The password to be included in the JWT payload. 11 | * Should meet the defined length requirement (e.g., 6 characters). 12 | * @returns {string|null} A JWT string if the username and password are valid. 13 | * Returns null if the username is not a valid email or 14 | * the password does not meet the length requirement. 15 | */ 16 | function signJwt(username, password) { 17 | // Your code here 18 | } 19 | 20 | /** 21 | * Verifies a JWT using a secret key. 22 | * 23 | * @param {string} token - The JWT string to verify. 24 | * @returns {boolean} Returns true if the token is valid and verified using the secret key. 25 | * Returns false if the token is invalid, expired, or not verified 26 | * using the secret key. 27 | */ 28 | function verifyJwt(token) { 29 | // Your code here 30 | } 31 | 32 | /** 33 | * Decodes a JWT to reveal its payload without verifying its authenticity. 34 | * 35 | * @param {string} token - The JWT string to decode. 36 | * @returns {object|false} The decoded payload of the JWT if the token is a valid JWT format. 37 | * Returns false if the token is not a valid JWT format. 38 | */ 39 | function decodeJwt(token) { 40 | // Your code here 41 | } 42 | 43 | 44 | module.exports = { 45 | signJwt, 46 | verifyJwt, 47 | decodeJwt, 48 | jwtPassword, 49 | }; 50 | -------------------------------------------------------------------------------- /week-2/02-nodejs/solutions/fileServer.solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | You need to create an express HTTP server in Node.js which will handle the logic of a file server. 3 | - Use built in Node.js `fs` module 4 | The expected API endpoints are defined below, 5 | 1. GET /files - Returns a list of files present in `./files/` directory 6 | Response: 200 OK with an array of file names in JSON format. 7 | Example: GET http://localhost:3000/files 8 | 2. GET /file/:filename - Returns content of given file by name 9 | Description: Use the filename from the request path parameter to read the file from `./files/` directory 10 | Response: 200 OK with the file content as the response body if found, or 404 Not Found if not found. Should return `File not found` as text if file is not found 11 | Example: GET http://localhost:3000/file/example.txt 12 | - For any other route not defined in the server return 404 13 | Testing the server - run `npm run test-fileServer` command in terminal 14 | */ 15 | const express = require('express'); 16 | const fs = require('fs'); 17 | const path = require('path'); 18 | const app = express(); 19 | 20 | app.get('/files', function (req, res) { 21 | fs.readdir(path.join(__dirname, './files/'), (err, files) => { 22 | if (err) { 23 | return res.status(500).json({ error: 'Failed to retrieve files' }); 24 | } 25 | res.json(files); 26 | }); 27 | }); 28 | 29 | app.get('/file/:filename', function (req, res) { 30 | const filepath = path.join(__dirname, './files/', req.params.filename); 31 | 32 | fs.readFile(filepath, 'utf8', (err, data) => { 33 | if (err) { 34 | return res.status(404).send('File not found'); 35 | } 36 | res.send(data); 37 | }); 38 | }); 39 | 40 | app.all('*', (req, res) => { 41 | res.status(404).send('Route not found'); 42 | }); 43 | 44 | module.exports = app; 45 | -------------------------------------------------------------------------------- /week-3/03-mongo/solution/routes/user.js: -------------------------------------------------------------------------------- 1 | const { Router } = require("express"); 2 | const router = Router(); 3 | const userMiddleware = require("../middleware/user"); 4 | const { User, Course } = require("../db"); 5 | const { default: mongoose } = require("mongoose"); 6 | 7 | // User Routes 8 | router.post('/signup', (req, res) => { 9 | // Implement user signup logic 10 | const username = req.body.username; 11 | const password = req.body.password; 12 | User.create({ 13 | username, 14 | password 15 | }) 16 | res.json({ 17 | message: "User created successfully" 18 | }) 19 | }); 20 | 21 | router.get('/courses', async (req, res) => { 22 | // Implement listing all courses logic 23 | // Implement fetching all courses logic 24 | const response = await Course.find({}); 25 | 26 | res.json({ 27 | courses: response 28 | }) 29 | }); 30 | 31 | router.post('/courses/:courseId', userMiddleware, async(req, res) => { 32 | // Implement course purchase logic 33 | const courseId = req.params.courseId; 34 | const username = req.headers.username; 35 | 36 | await User.updateOne({ 37 | username: username 38 | }, { 39 | "$push": { 40 | purchasedCourses: courseId 41 | } 42 | }) 43 | res.json({ 44 | message: "Purchase complete!" 45 | }) 46 | }); 47 | 48 | router.get('/purchasedCourses', userMiddleware, async (req, res) => { 49 | // Implement fetching purchased courses logic 50 | const user = await User.findOne({ 51 | username: req.headers.username 52 | }); 53 | 54 | console.log(user.purchasedCourses); 55 | const courses = await Course.find({ 56 | _id: { 57 | "$in": user.purchasedCourses 58 | } 59 | }); 60 | 61 | res.json({ 62 | courses: courses 63 | }) 64 | }); 65 | 66 | module.exports = router -------------------------------------------------------------------------------- /01-js/tests/palindrome.test.js: -------------------------------------------------------------------------------- 1 | const isPalindrome = require('../medium/palindrome'); 2 | 3 | describe('isPalindrome', () => { 4 | test('returns true for palindromes', () => { 5 | expect(isPalindrome('level')).toBe(true); 6 | expect(isPalindrome('racecar')).toBe(true); 7 | }); 8 | 9 | test('returns false for non-palindromes', () => { 10 | expect(isPalindrome('hello')).toBe(false); 11 | expect(isPalindrome('openai')).toBe(false); 12 | expect(isPalindrome('abcde')).toBe(false); 13 | }); 14 | 15 | test('returns true for an empty string', () => { 16 | expect(isPalindrome('')).toBe(true); 17 | }); 18 | 19 | test('handles case-insensitivity correctly', () => { 20 | expect(isPalindrome('Anna')).toBe(true); 21 | expect(isPalindrome('aNnA')).toBe(true); 22 | expect(isPalindrome('Madam')).toBe(true); 23 | expect(isPalindrome('MaDaM')).toBe(true); 24 | expect(isPalindrome('RaCeCaR')).toBe(true); 25 | expect(isPalindrome('rAcEcAr')).toBe(true); 26 | }); 27 | 28 | test('returns true for single-character strings', () => { 29 | expect(isPalindrome('a')).toBe(true); 30 | expect(isPalindrome('z')).toBe(true); 31 | expect(isPalindrome('5')).toBe(true); 32 | expect(isPalindrome('@')).toBe(true); 33 | }); 34 | 35 | test('returns true for strings with spaces', () => { 36 | expect(isPalindrome('race car')).toBe(true); 37 | expect( 38 | isPalindrome('A man a plan a canal Panama') 39 | ).toBe(true); 40 | expect( 41 | isPalindrome('Was it a car or a cat I saw') 42 | ).toBe(true); 43 | }); 44 | 45 | test('returns true for strings with punctuation marks', () => { 46 | expect( 47 | isPalindrome('Able, was I ere I saw Elba!') 48 | ).toBe(true); 49 | expect( 50 | isPalindrome('Eva, can I see bees in a cave?') 51 | ).toBe(true); 52 | expect(isPalindrome('Mr. Owl ate my metal worm.')).toBe( 53 | true 54 | ); 55 | expect( 56 | isPalindrome('A man, a plan, a canal. Panama') 57 | ).toBe(true); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /week-3/02-jwt/tests/index.spec.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const { 3 | signJwt, 4 | verifyJwt, 5 | decodeJwt, 6 | jwtPassword 7 | } = require('../'); 8 | 9 | describe('signJwt', () => { 10 | test('signs a jwt correctly', () => { 11 | const token = signJwt('kirat@gmail.com', '123456' ); 12 | const decoded = jwt.decode(token); 13 | expect(decoded.username).toBe('kirat@gmail.com'); 14 | }); 15 | 16 | test('returns null if invalid email', () => { 17 | const token = signJwt('kirat', '123456'); 18 | expect(token).toBe(null); 19 | }); 20 | 21 | test('returns null if small pw', () => { 22 | const token = signJwt('kirat@gmail.com', '12345'); 23 | expect(token).toBe(null); 24 | }); 25 | 26 | }); 27 | 28 | describe('decodeJwt', () => { 29 | test('decodes a jwt with diff password correctly', () => { 30 | const token = jwt.sign({ username: 'kirat@gmail.com', password: '123456' }, "randomPassword"); 31 | const decoded = decodeJwt(token); 32 | expect(decoded).toBe(true); 33 | }); 34 | 35 | test('decodes a jwt with same password correctly', () => { 36 | const token = jwt.sign({ username: 'kirat@gmail.com', password: '123456' }, jwtPassword); 37 | const decoded = decodeJwt(token); 38 | expect(decoded).toBe(true); 39 | }); 40 | 41 | test('cant decode a non jwt string', () => { 42 | const decoded = decodeJwt("token"); 43 | expect(decoded).toBe(false); 44 | }); 45 | 46 | }); 47 | 48 | describe('verifyJwt', () => { 49 | test('cant decode a jwt with diff password correctly', () => { 50 | const token = jwt.sign({ username: 'kirat@gmail.com', password: '123456' }, "randomPassword"); 51 | const decoded = verifyJwt(token); 52 | expect(decoded).toBe(false); 53 | }); 54 | 55 | test('decodes a jwt with same password correctly', () => { 56 | const token = jwt.sign({ username: 'kirat@gmail.com', password: '123456' }, jwtPassword); 57 | const decoded = verifyJwt(token); 58 | expect(decoded).toBe(true); 59 | }); 60 | 61 | test('cant decode a non jwt string', () => { 62 | const decoded = verifyJwt("token"); 63 | expect(decoded).toBe(false); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /01-js/hard/calculator.js: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a class `Calculator` having below methods 3 | - initialise a result variable in the constructor and keep updating it after every arithmetic operation 4 | - add: takes a number and adds it to the result 5 | - subtract: takes a number and subtracts it from the result 6 | - multiply: takes a number and multiply it to the result 7 | - divide: takes a number and divide it to the result 8 | - clear: makes the `result` variable to 0 9 | - getResult: returns the value of `result` variable 10 | - calculate: takes a string expression which can take multi-arithmetic operations and give its result 11 | example input: `10 + 2 * ( 6 - (4 + 1) / 2) + 7` 12 | Points to Note: 13 | 1. the input can have multiple continuous spaces, you're supposed to avoid them and parse the expression correctly 14 | 2. the input can have invalid non-numerical characters like `5 + abc`, you're supposed to throw error for such inputs 15 | 16 | Once you've implemented the logic, test your code by running 17 | */ 18 | 19 | class Calculator { 20 | constructor() { 21 | this.result = 0; 22 | } 23 | 24 | add(number) { 25 | this.result += number; 26 | } 27 | subtract(number) { 28 | this.result -= number; 29 | } 30 | multiply(number) { 31 | this.result *= number; 32 | } 33 | divide(number) { 34 | if (number == 0) { 35 | throw new Error("Invalid input: result is not divisible by 0"); 36 | } 37 | this.result /= number; 38 | } 39 | clear() { 40 | this.result = 0; 41 | } 42 | 43 | getResult() { 44 | return this.result; 45 | } 46 | 47 | calculate(str) { 48 | this.clear() 49 | str = str.replace('/\s/g', ''); 50 | 51 | try { 52 | let result = eval(str); 53 | if (isNaN(result) || !isFinite(result)) { 54 | throw new Error("Invalid input: Unable to evaluate the expression"); 55 | } //bad result 56 | 57 | return this.result = result; //everything was good 58 | } catch (error) { 59 | throw new Error(error); 60 | } 61 | } 62 | } 63 | 64 | module.exports = Calculator; 65 | -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/solution/routes/admin.js: -------------------------------------------------------------------------------- 1 | const { Router } = require("express"); 2 | const adminMiddleware = require("../middleware/admin"); 3 | const { Admin, User, Course } = require("../db"); 4 | const {JWT_SECRET} = require("../config"); 5 | const router = Router(); 6 | const jwt = require("jsonwebtoken"); 7 | 8 | // Admin Routes 9 | router.post('/signup', async (req, res) => { 10 | // Implement admin signup logic 11 | const username = req.body.username; 12 | const password = req.body.password; 13 | 14 | // check if a user with this username already exists 15 | await Admin.create({ 16 | username: username, 17 | password: password 18 | }) 19 | 20 | res.json({ 21 | message: 'Admin created successfully' 22 | }) 23 | }); 24 | 25 | router.post('/signin', async (req, res) => { 26 | // Implement admin signup logic 27 | const username = req.body.username; 28 | const password = req.body.password; 29 | console.log(JWT_SECRET); 30 | 31 | const user = await User.find({ 32 | username, 33 | password 34 | }) 35 | if (user) { 36 | const token = jwt.sign({ 37 | username 38 | }, JWT_SECRET); 39 | 40 | res.json({ 41 | token 42 | }) 43 | } else { 44 | res.status(411).json({ 45 | message: "Incorrect email and pass" 46 | }) 47 | } 48 | }); 49 | 50 | 51 | router.post('/courses', adminMiddleware, async (req, res) => { 52 | // Implement course creation logic 53 | const title = req.body.title; 54 | const description = req.body.description; 55 | const imageLink = req.body.imageLink; 56 | const price = req.body.price; 57 | // zod 58 | const newCourse = await Course.create({ 59 | title, 60 | description, 61 | imageLink, 62 | price 63 | }) 64 | 65 | res.json({ 66 | message: 'Course created successfully', courseId: newCourse._id 67 | }) 68 | }); 69 | 70 | router.get('/courses', adminMiddleware, async (req, res) => { 71 | // Implement fetching all courses logic 72 | const response = await Course.find({}); 73 | 74 | res.json({ 75 | courses: response 76 | }) 77 | 78 | }); 79 | 80 | 81 | module.exports = router; -------------------------------------------------------------------------------- /week-1/offline-class-1/level-1/01-String.js: -------------------------------------------------------------------------------- 1 | // String handbook 2 | 3 | // String: length, indexOf(), lastIndexOf(), slice(), substring(), replace(), 4 | // split(), trim(), toUpperCase(), toLowerCase(), etc. 5 | 6 | // Run each function to see the output, play and learn by doing. 7 | 8 | // Length 9 | function getLength(str) { 10 | console.log("Original String:", str); 11 | console.log("Length:", str.length); 12 | } 13 | getLength("Hello World"); 14 | 15 | // indexOf 16 | function findIndexOf(str, target) { 17 | console.log("Original String:", str); 18 | console.log("Index:", str.indexOf(target)); 19 | } 20 | findIndexOf("Hello World", "World"); 21 | 22 | // lastIndexOf 23 | function findLastIndexOf(str, target) { 24 | console.log("Original String:", str); 25 | console.log("Index:", str.lastIndexOf(target)); 26 | } 27 | findLastIndexOf("Hello World World", "World"); 28 | 29 | // slice 30 | function getSlice(str, start, end) { 31 | console.log("Original String:", str); 32 | console.log("After slice:", str.slice(start, end)); 33 | } 34 | getSlice("Hello World", 0, 5); 35 | 36 | // substring 37 | function getSubstring(str, start, end) { 38 | console.log("Original String:", str); 39 | console.log("After substring:", str.substring(start, end)); 40 | } 41 | getSubstring("Hello World", 0, 5); 42 | 43 | // replace 44 | function replaceString(str, target, replacement) { 45 | console.log("Original String:", str); 46 | console.log("After replace:", str.replace(target, replacement)); 47 | } 48 | replaceString("Hello World", "World", "JavaScript"); 49 | 50 | // split 51 | function splitString(str, separator) { 52 | console.log("Original String:", str); 53 | console.log("After split:", str.split(separator)); 54 | } 55 | splitString("Hello World", " "); 56 | 57 | // trim 58 | function trimString(str) { 59 | console.log("Original String:", str); 60 | console.log("After trim:", str.trim()); 61 | } 62 | trimString(" Hello World "); 63 | 64 | // toUpperCase 65 | function toUpper(str) { 66 | console.log("Original String:", str); 67 | console.log("After toUpperCase:", str.toUpperCase()); 68 | } 69 | toUpper("Hello World"); 70 | 71 | // toLowerCase 72 | function toLower(str) { 73 | console.log("Original String:", str); 74 | console.log("After toLowerCase:", str.toLowerCase()); 75 | } 76 | toLower("Hello World"); 77 | -------------------------------------------------------------------------------- /01-js/tests/todo-list.test.js: -------------------------------------------------------------------------------- 1 | const Todo = require('../hard/todo-list'); 2 | 3 | describe('Todo', () => { 4 | let todoList; 5 | 6 | beforeEach(() => { 7 | todoList = new Todo(); 8 | }); 9 | 10 | test('add and getAll', () => { 11 | todoList.add('Task 1'); 12 | todoList.add('Task 2'); 13 | todoList.add('Task 3'); 14 | 15 | expect(todoList.getAll()).toEqual([ 16 | 'Task 1', 17 | 'Task 2', 18 | 'Task 3', 19 | ]); 20 | }); 21 | 22 | test('remove', () => { 23 | todoList.add('Task 1'); 24 | todoList.add('Task 2'); 25 | todoList.add('Task 3'); 26 | 27 | todoList.remove(1); 28 | expect(todoList.getAll()).toEqual(['Task 1', 'Task 3']); 29 | 30 | todoList.remove(0); 31 | expect(todoList.getAll()).toEqual(['Task 3']); 32 | 33 | todoList.remove(2); 34 | expect(todoList.getAll()).toEqual(['Task 3']); 35 | }); 36 | 37 | test('update', () => { 38 | todoList.add('Task 1'); 39 | todoList.add('Task 2'); 40 | todoList.add('Task 3'); 41 | 42 | todoList.update(1, 'Updated Task 2'); 43 | expect(todoList.get(1)).toBe('Updated Task 2'); 44 | 45 | todoList.update(3, 'Invalid Task'); 46 | expect(todoList.getAll()).toEqual([ 47 | 'Task 1', 48 | 'Updated Task 2', 49 | 'Task 3', 50 | ]); 51 | }); 52 | 53 | test('get', () => { 54 | todoList.add('Task 1'); 55 | todoList.add('Task 2'); 56 | todoList.add('Task 3'); 57 | 58 | expect(todoList.get(0)).toBe('Task 1'); 59 | expect(todoList.get(2)).toBe('Task 3'); 60 | expect(todoList.get(3)).toBeNull(); 61 | }); 62 | 63 | test('clear', () => { 64 | todoList.add('Task 1'); 65 | todoList.add('Task 2'); 66 | todoList.add('Task 3'); 67 | 68 | todoList.clear(); 69 | expect(todoList.getAll()).toEqual([]); 70 | }); 71 | 72 | test('remove and update with invalid indexes', () => { 73 | todoList.add('Task 1'); 74 | todoList.add('Task 2'); 75 | 76 | todoList.remove(5); 77 | expect(todoList.getAll()).toEqual(['Task 1', 'Task 2']); 78 | 79 | todoList.update(3, 'Updated Task'); 80 | expect(todoList.getAll()).toEqual(['Task 1', 'Task 2']); 81 | }); 82 | 83 | test('add duplicate tasks', () => { 84 | todoList.add('Task 1'); 85 | todoList.add('Task 2'); 86 | todoList.add('Task 1'); 87 | todoList.add('Task 3'); 88 | 89 | expect(todoList.getAll()).toEqual([ 90 | 'Task 1', 91 | 'Task 2', 92 | 'Task 1', 93 | 'Task 3', 94 | ]); 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /week-2/02-nodejs/todoServer.js: -------------------------------------------------------------------------------- 1 | /** 2 | You need to create an express HTTP server in Node.js which will handle the logic of a todo list app. 3 | - Don't use any database, just store all the data in an array to store the todo list data (in-memory) 4 | - Hard todo: Try to save responses in files, so that even if u exit the app and run it again, the data remains (similar to databases) 5 | 6 | Each todo has a title and a description. The title is a string and the description is a string. 7 | Each todo should also get an unique autogenerated id every time it is created 8 | The expected API endpoints are defined below, 9 | 1.GET /todos - Retrieve all todo items 10 | Description: Returns a list of all todo items. 11 | Response: 200 OK with an array of todo items in JSON format. 12 | Example: GET http://localhost:3000/todos 13 | 14 | 2.GET /todos/:id - Retrieve a specific todo item by ID 15 | Description: Returns a specific todo item identified by its ID. 16 | Response: 200 OK with the todo item in JSON format if found, or 404 Not Found if not found. 17 | Example: GET http://localhost:3000/todos/123 18 | 19 | 3. POST /todos - Create a new todo item 20 | Description: Creates a new todo item. 21 | Request Body: JSON object representing the todo item. 22 | Response: 201 Created with the ID of the created todo item in JSON format. eg: {id: 1} 23 | Example: POST http://localhost:3000/todos 24 | Request Body: { "title": "Buy groceries", "completed": false, description: "I should buy groceries" } 25 | 26 | 4. PUT /todos/:id - Update an existing todo item by ID 27 | Description: Updates an existing todo item identified by its ID. 28 | Request Body: JSON object representing the updated todo item. 29 | Response: 200 OK if the todo item was found and updated, or 404 Not Found if not found. 30 | Example: PUT http://localhost:3000/todos/123 31 | Request Body: { "title": "Buy groceries", "completed": true } 32 | 33 | 5. DELETE /todos/:id - Delete a todo item by ID 34 | Description: Deletes a todo item identified by its ID. 35 | Response: 200 OK if the todo item was found and deleted, or 404 Not Found if not found. 36 | Example: DELETE http://localhost:3000/todos/123 37 | 38 | - For any other route not defined in the server return 404 39 | 40 | Testing the server - run `npm run test-todoServer` command in terminal 41 | */ 42 | const express = require('express'); 43 | const bodyParser = require('body-parser'); 44 | 45 | const app = express(); 46 | 47 | app.use(bodyParser.json()); 48 | 49 | module.exports = app; -------------------------------------------------------------------------------- /week-1/offline-class-1/level-1/03-Array.js: -------------------------------------------------------------------------------- 1 | // Array handbook 2 | 3 | // Array: push(), pop(), shift(), unshift(), splice(), slice(), 4 | // concat(), forEach(), map(), filter(), reduce(), find(), sort() 5 | 6 | // Run each function to see the output, play and learn by doing. 7 | 8 | // push() 9 | function pushExample(arr, element) { 10 | console.log("Original Array:", arr); 11 | 12 | arr.push(element); 13 | console.log("After push:", arr); 14 | } 15 | pushExample([1, 2, 3], 4); 16 | 17 | // pop() 18 | function popExample(arr) { 19 | console.log("Original Array:", arr); 20 | 21 | arr.pop(); 22 | console.log("After pop:", arr); 23 | } 24 | popExample([1, 2, 3]); 25 | 26 | // shift() 27 | function shiftExample(arr) { 28 | console.log("Original Array:", arr); 29 | 30 | arr.shift(); 31 | console.log("After shift:", arr); 32 | } 33 | shiftExample([1, 2, 3]); 34 | 35 | // unshift() 36 | function unshiftExample(arr, element) { 37 | console.log("Original Array:", arr); 38 | 39 | arr.unshift(element); 40 | console.log("After unshift:", arr); 41 | } 42 | unshiftExample([1, 2, 3], 0); 43 | 44 | // concat() 45 | function concatExample(arr1, arr2) { 46 | console.log("Original Arrays:", arr1, arr2); 47 | 48 | let arr3 = arr1.concat(arr2); 49 | console.log("After concat:", arr3); 50 | } 51 | concatExample([1, 2, 3], [4, 5, 6]); 52 | 53 | // forEach() 54 | function forEachExample(arr) { 55 | console.log("Original Array:", arr); 56 | 57 | arr.forEach(function(item, index) { 58 | console.log(item, index); 59 | }); 60 | } 61 | forEachExample([1, 2, 3]); 62 | 63 | // map() 64 | function mapExample(arr) { 65 | console.log("Original Array:", arr); 66 | 67 | let newArr = arr.map(function(item) { 68 | return item * 2; 69 | }); 70 | console.log("After map:", newArr); 71 | } 72 | mapExample([1, 2, 3]); 73 | 74 | // filter() 75 | function filterExample(arr) { 76 | console.log("Original Array:", arr); 77 | 78 | let newArr = arr.filter(function(item) { 79 | return item > 3; 80 | }); 81 | console.log("After filter:", newArr); 82 | } 83 | filterExample([1, 2, 3, 4, 5]); 84 | 85 | // find() 86 | function findExample(arr) { 87 | console.log("Original Array:", arr); 88 | 89 | let found = arr.find(function(item) { 90 | return item > 3; 91 | }); 92 | console.log("After find:", found); 93 | } 94 | findExample([1, 2, 3, 4, 5]); 95 | 96 | // sort() 97 | function sortExample(arr) { 98 | console.log("Original Array:", arr); 99 | 100 | arr.sort(function(a, b) { 101 | return a - b; 102 | }); 103 | console.log("After sort:", arr); 104 | } 105 | sortExample([5, 2, 3, 4, 1]); 106 | -------------------------------------------------------------------------------- /week-5/solutions/level-1/BusinessCard.jsx: -------------------------------------------------------------------------------- 1 | export function BusinessCard(props) { 2 | return ( 3 |
4 |

{props.name}

5 |

{props.description}

6 |

Interests

7 |
    8 | {props.interests.map((interest) => ( 9 |
  • 10 | {interest} 11 |
  • 12 | ))} 13 |
14 |
15 | 16 | LinkedIn 17 | 18 |
19 | 20 | Twitter 21 | 22 | {props.otherSocialMedia && ( 23 | 24 | {props.otherSocialMedia.label} 25 | 26 | )} 27 |
28 |
29 | ); 30 | } 31 | 32 | // Styles 33 | const styles = { 34 | card: { 35 | border: '1px solid #ddd', 36 | borderRadius: '8px', 37 | padding: '20px', 38 | margin: '20px', 39 | maxWidth: '400px', 40 | boxShadow: '0 4px 8px rgba(0, 0, 0, 0.1)', 41 | backgroundColor: '#f8f9fa' 42 | }, 43 | name: { 44 | fontSize: '24px', 45 | marginBottom: '10px', 46 | color: '#333', 47 | }, 48 | description: { 49 | fontSize: '16px', 50 | color: '#555', 51 | marginBottom: '15px', 52 | }, 53 | socialLinks: { 54 | display: 'flex', 55 | marginBottom: '15px', 56 | }, 57 | link: { 58 | textDecoration: 'none', 59 | color: '#fff', // Text color 60 | padding: '10px 15px', // Padding for the button 61 | borderRadius: '5px', // Border radius for rounded corners 62 | backgroundColor: '#007BFF', // Background color for the button 63 | display: 'inline-block', // Display as inline-block to be side by side 64 | margin: '10px', // Margin between buttons 65 | boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)', // Box shadow for a subtle lift 66 | }, 67 | interestsHeader: { 68 | fontSize: '18px', 69 | marginBottom: '10px', 70 | color: '#333', 71 | }, 72 | interestsList: { 73 | listStyle: 'none', 74 | padding: 0, 75 | margin: 0, 76 | }, 77 | interestItem: { 78 | fontSize: '14px', 79 | marginBottom: '5px', 80 | color: '#555', 81 | }, 82 | }; -------------------------------------------------------------------------------- /week-3/04-mongo-with-jwt-auth/README.md: -------------------------------------------------------------------------------- 1 | ## Create a course selling website 2 | 3 | ### Description 4 | 5 | Same as the last assignment but you need to use jwts for authentication. 6 | We have introduced the signgin endpoints for both users and admins. 7 | For this one, in every authenticated requests, you need to send the jwt in headers (Authorization : "Bearer "). 8 | You need to use mongodb to store all the data persistently. 9 | 10 | ## Routes 11 | 12 | ### Admin Routes: 13 | 14 | - POST /admin/signup 15 | Description: Creates a new admin account. 16 | Input Body: { username: 'admin', password: 'pass' } 17 | Output: { message: 'Admin created successfully' } 18 | - POST /admin/signin 19 | Description: Logs in an admin account. 20 | Input Body: { username: 'admin', password: 'pass' } 21 | Output: { token: 'your-token' } 22 | - POST /admin/courses 23 | Description: Creates a new course. 24 | Input: Headers: { 'Authorization': 'Bearer ' }, Body: { title: 'course title', description: 'course description', price: 100, imageLink: 'https://linktoimage.com' } 25 | Output: { message: 'Course created successfully', courseId: "new course id" } 26 | - GET /admin/courses 27 | Description: Returns all the courses. 28 | Input: Headers: { 'Authorization': 'Bearer ' } 29 | Output: { courses: [ { id: 1, title: 'course title', description: 'course description', price: 100, imageLink: 'https://linktoimage.com', published: true }, ... ] } 30 | 31 | ### User routes 32 | 33 | - POST /users/signup 34 | Description: Creates a new user account. 35 | Input: { username: 'user', password: 'pass' } 36 | Output: { message: 'User created successfully' } 37 | - POST /users/signin 38 | Description: Logs in a user account. 39 | Input: { username: 'user', password: 'pass' } 40 | Output: { token: 'your-token' } 41 | - GET /users/courses 42 | Description: Lists all the courses. 43 | Input: Headers: { 'Authorization': 'Bearer ' } 44 | Output: { courses: [ { id: 1, title: 'course title', description: 'course description', price: 100, imageLink: 'https://linktoimage.com', published: true }, ... ] } 45 | - POST /users/courses/:courseId 46 | Description: Purchases a course. courseId in the URL path should be replaced with the ID of the course to be purchased. 47 | Input: Headers: { 'Authorization': 'Bearer ' } 48 | Output: { message: 'Course purchased successfully' } 49 | - GET /users/purchasedCourses 50 | Description: Lists all the courses purchased by the user. 51 | Input: Headers: { 'Authorization': 'Bearer ' } 52 | Output: { purchasedCourses: [ { id: 1, title: 'course title', description: 'course description', price: 100, imageLink: 'https://linktoimage.com', published: true }, ... ] } 53 | -------------------------------------------------------------------------------- /01-js/tests/expenditure-analysis.test.js: -------------------------------------------------------------------------------- 1 | const calculateTotalSpentByCategory = require('../easy/expenditure-analysis'); 2 | 3 | describe('calculateTotalSpentByCategory', () => { 4 | test('returns the correct total spent for a single transaction', () => { 5 | const transactions = [ 6 | { 7 | id: 1, 8 | timestamp: 1656076800000, 9 | price: 10, 10 | category: 'Food', 11 | itemName: 'Pizza', 12 | }, 13 | ]; 14 | 15 | const result = 16 | calculateTotalSpentByCategory(transactions); 17 | 18 | expect(result).toEqual([ 19 | { category: 'Food', totalSpent: 10 }, 20 | ]); 21 | }); 22 | 23 | test('returns the correct total spent for each category', () => { 24 | const transactions = [ 25 | { 26 | id: 1, 27 | timestamp: 1656076800000, 28 | price: 10, 29 | category: 'Food', 30 | itemName: 'Pizza', 31 | }, 32 | { 33 | id: 2, 34 | timestamp: 1656259600000, 35 | price: 20, 36 | category: 'Food', 37 | itemName: 'Burger', 38 | }, 39 | { 40 | id: 3, 41 | timestamp: 1656019200000, 42 | price: 15, 43 | category: 'Clothing', 44 | itemName: 'T-Shirt', 45 | }, 46 | { 47 | id: 4, 48 | timestamp: 1656364800000, 49 | price: 30, 50 | category: 'Electronics', 51 | itemName: 'Headphones', 52 | }, 53 | { 54 | id: 5, 55 | timestamp: 1656105600000, 56 | price: 25, 57 | category: 'Clothing', 58 | itemName: 'Jeans', 59 | }, 60 | ]; 61 | 62 | const result = 63 | calculateTotalSpentByCategory(transactions); 64 | 65 | expect(result).toEqual([ 66 | { category: 'Food', totalSpent: 30 }, 67 | { category: 'Clothing', totalSpent: 40 }, 68 | { category: 'Electronics', totalSpent: 30 }, 69 | ]); 70 | }); 71 | 72 | test('returns an empty array when given an empty input', () => { 73 | const transactions = []; 74 | const result = 75 | calculateTotalSpentByCategory(transactions); 76 | expect(result).toEqual([]); 77 | }); 78 | 79 | test('returns the correct total spent when multiple transactions have the same category', () => { 80 | const transactions = [ 81 | { 82 | id: 1, 83 | timestamp: 1656076800000, 84 | price: 10, 85 | category: 'Food', 86 | itemName: 'Pizza', 87 | }, 88 | { 89 | id: 2, 90 | timestamp: 1656105600000, 91 | price: 20, 92 | category: 'Food', 93 | itemName: 'Burger', 94 | }, 95 | { 96 | id: 3, 97 | timestamp: 1656134400000, 98 | price: 30, 99 | category: 'Food', 100 | itemName: 'Sushi', 101 | }, 102 | ]; 103 | 104 | const result = 105 | calculateTotalSpentByCategory(transactions); 106 | 107 | expect(result).toEqual([ 108 | { category: 'Food', totalSpent: 60 }, 109 | ]); 110 | }); 111 | }); 112 | -------------------------------------------------------------------------------- /week-3/03-mongo/README.md: -------------------------------------------------------------------------------- 1 | ## Create a course selling website 2 | 3 | ### Description 4 | You need to implement a course selling app. Make sure you setup your own mongodb instance before starting. 5 | It needs to support two types of users - 6 | 1. Admins 7 | 2. Users 8 | 9 | Admins are allowed to sign up, create courses. 10 | Users are allowed to sign up, view courses, purchase courses. 11 | This in the real world would translate to an app like udemy. 12 | 13 | This one doesn't use authentication the right way. We will learn how to do that in the next assignment. 14 | For this one, in every authenticated requests, you need to send the username and password in the headers (and not the jwt). 15 | This is the reason why this assignment doesn't have a sign in route. 16 | 17 | You need to use mongodb to store all the data persistently. 18 | 19 | ## Routes 20 | ### Admin Routes: 21 | - POST /admin/signup 22 | Description: Creates a new admin account. 23 | Input Body: { username: 'admin', password: 'pass' } 24 | Output: { message: 'Admin created successfully' } 25 | - POST /admin/courses 26 | Description: Creates a new course. 27 | Input: Headers: { 'username': 'username', 'password': 'password' }, Body: { title: 'course title', description: 'course description', price: 100, imageLink: 'https://linktoimage.com' } 28 | Output: { message: 'Course created successfully', courseId: "new course id" } 29 | - GET /admin/courses 30 | Description: Returns all the courses. 31 | Input: Headers: { 'username': 'username', 'password': 'password' } 32 | Output: { courses: [ { id: 1, title: 'course title', description: 'course description', price: 100, imageLink: 'https://linktoimage.com', published: true }, ... ] } 33 | 34 | ### User routes 35 | - POST /users/signup 36 | Description: Creates a new user account. 37 | Input: { username: 'user', password: 'pass' } 38 | Output: { message: 'User created successfully' } 39 | - GET /users/courses 40 | Description: Lists all the courses. 41 | Input: Headers: { 'username': 'username', 'password': 'password' } 42 | Output: { courses: [ { id: 1, title: 'course title', description: 'course description', price: 100, imageLink: 'https://linktoimage.com', published: true }, ... ] } 43 | - POST /users/courses/:courseId 44 | Description: Purchases a course. courseId in the URL path should be replaced with the ID of the course to be purchased. 45 | Input: Headers: { 'username': 'username', 'password': 'password' } 46 | Output: { message: 'Course purchased successfully' } 47 | - GET /users/purchasedCourses 48 | Description: Lists all the courses purchased by the user. 49 | Input: Headers: { 'username': 'username', 'password': 'password' } 50 | Output: { purchasedCourses: [ { id: 1, title: 'course title', description: 'course description', price: 100, imageLink: 'https://linktoimage.com', published: true }, ... ] } -------------------------------------------------------------------------------- /week-2/02-nodejs/solutions/todoServer.solution.file.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | const fs = require("fs"); 4 | 5 | const app = express(); 6 | 7 | app.use(bodyParser.json()); 8 | 9 | function findIndex(arr, id) { 10 | for (let i = 0; i < arr.length; i++) { 11 | if (arr[i].id === id) return i; 12 | } 13 | return -1; 14 | } 15 | 16 | function removeAtIndex(arr, index) { 17 | let newArray = []; 18 | for (let i = 0; i < arr.length; i++) { 19 | if (i !== index) newArray.push(arr[i]); 20 | } 21 | return newArray; 22 | } 23 | 24 | app.get('/todos', (req, res) => { 25 | fs.readFile("todos.json", "utf8", function(err, data) { 26 | if (err) throw err; 27 | res.json(JSON.parse(data)); 28 | }); 29 | }); 30 | 31 | app.get('/todos/:id', (req, res) => { 32 | fs.readFile("todos.json", "utf8", function(err, data) { 33 | if (err) throw err; 34 | const todos = JSON.parse(data); 35 | const todoIndex = findIndex(todos, parseInt(req.params.id)); 36 | if (todoIndex === -1) { 37 | res.status(404).send(); 38 | } else { 39 | res.json(todos[todoIndex]); 40 | } 41 | }); 42 | }); 43 | 44 | app.post('/todos', function(req, res) { 45 | const newTodo = { 46 | id: Math.floor(Math.random() * 1000000), // unique random id 47 | title: req.body.title, 48 | description: req.body.description 49 | }; 50 | fs.readFile("todos.json", "utf8", (err, data) => { 51 | if (err) throw err; 52 | const todos = JSON.parse(data); 53 | todos.push(newTodo); 54 | fs.writeFile("todos.json", JSON.stringify(todos), (err) => { 55 | if (err) throw err; 56 | res.status(201).json(newTodo); 57 | }); 58 | }); 59 | }); 60 | 61 | app.put('/todos/:id', function(req, res) { 62 | fs.readFile("todos.json", "utf8", (err, data) => { 63 | if (err) throw err; 64 | const todos = JSON.parse(data); 65 | const todoIndex = findIndex(todos, parseInt(req.params.id)); 66 | if (todoIndex === -1) { 67 | res.status(404).send(); 68 | } else { 69 | const updatedTodo = { 70 | id: todos[todoIndex].id, 71 | title: req.body.title, 72 | description: req.body.description 73 | }; 74 | todos[todoIndex] = updatedTodo; 75 | fs.writeFile("todos.json", JSON.stringify(todos), (err) => { 76 | if (err) throw err; 77 | res.status(200).json(updatedTodo); 78 | }); 79 | } 80 | }); 81 | }); 82 | 83 | app.delete('/todos/:id', function(req, res) { 84 | 85 | fs.readFile("todos.json", "utf8", (err, data) => { 86 | if (err) throw err; 87 | let todos = JSON.parse(data); 88 | const todoIndex = findIndex(todos, parseInt(req.params.id)); 89 | if (todoIndex === -1) { 90 | res.status(404).send(); 91 | } else { 92 | todos = removeAtIndex(todos, todoIndex); 93 | fs.writeFile("todos.json", JSON.stringify(todos), (err) => { 94 | if (err) throw err; 95 | res.status(200).send(); 96 | }); 97 | } 98 | }); 99 | }); 100 | 101 | // for all other routes, return 404 102 | app.use((req, res, next) => { 103 | res.status(404).send(); 104 | }); 105 | 106 | module.exports = app; -------------------------------------------------------------------------------- /01-js/tests/calculator.test.js: -------------------------------------------------------------------------------- 1 | const Calculator = require('../hard/calculator'); 2 | 3 | describe('Calculator', () => { 4 | let calc; 5 | 6 | beforeEach(() => { 7 | calc = new Calculator(); 8 | }); 9 | 10 | afterEach(() => { 11 | calc.clear(); 12 | }); 13 | 14 | test('addition', () => { 15 | calc.add(5); 16 | expect(calc.getResult()).toBe(5); 17 | 18 | calc.add(3); 19 | expect(calc.getResult()).toBe(8); 20 | }); 21 | 22 | test('subtraction', () => { 23 | calc.subtract(5); 24 | expect(calc.getResult()).toBe(-5); 25 | 26 | calc.subtract(3); 27 | expect(calc.getResult()).toBe(-8); 28 | }); 29 | 30 | test('multiplication', () => { 31 | calc.add(4); 32 | calc.multiply(3); 33 | expect(calc.getResult()).toBe(12); 34 | 35 | calc.multiply(0); 36 | expect(calc.getResult()).toBe(0); 37 | }); 38 | 39 | test('division', () => { 40 | calc.add(12); 41 | 42 | calc.divide(4); 43 | expect(calc.getResult()).toBe(3); 44 | 45 | expect(() => calc.divide(0)).toThrow(Error); 46 | expect(calc.getResult()).toBe(3); 47 | }); 48 | 49 | test('clear', () => { 50 | calc.add(5); 51 | calc.clear(); 52 | expect(calc.getResult()).toBe(0); 53 | }); 54 | 55 | test('calculate addition and multiplication', () => { 56 | calc.calculate('2 + 3 * 4'); 57 | expect(calc.getResult()).toBe(14); 58 | }); 59 | 60 | test('calculate division in expression', () => { 61 | calc.calculate('( 15 + 3) / 6 '); 62 | expect(calc.getResult()).toBe(3); 63 | }); 64 | 65 | test('calculate subtraction in expression', () => { 66 | calc.calculate('10 - (4 + 2)'); 67 | expect(calc.getResult()).toBe(4); 68 | }); 69 | 70 | test('calculate complex expression', () => { 71 | calc.calculate('(2 + 3) * (6 - (4 + 1) / 2) + 7'); 72 | expect(calc.getResult()).toBe(24.5); 73 | }); 74 | test('calculate complex expression with spaces', () => { 75 | calc.calculate( 76 | '10 + 2 * ( 6 - (4 + 1) / 2) + 7' 77 | ); 78 | expect(calc.getResult()).toBe(24); 79 | }); 80 | 81 | test('calculate expression with decimals', () => { 82 | calc.calculate('(2.5 + 1.5) * 3'); 83 | expect(calc.getResult()).toBe(12); 84 | }); 85 | 86 | test('calculate expression with invalid characters', () => { 87 | expect(() => calc.calculate('5 + abc')).toThrow(Error); 88 | expect(() => 89 | calc.calculate('10 * (2 + 3) + xyz') 90 | ).toThrow(Error); 91 | }); 92 | 93 | test('calculate division by zero', () => { 94 | expect(() => calc.calculate('10 / 0')).toThrow(Error); 95 | }); 96 | 97 | test('multiplication with negative numbers', () => { 98 | calc.add(-5); 99 | calc.multiply(-3); 100 | expect(calc.getResult()).toBe(15); 101 | 102 | calc.multiply(0); 103 | expect(calc.getResult()).toBe(0); 104 | }); 105 | 106 | test('division with decimal numbers', () => { 107 | calc.add(10); 108 | calc.divide(3); 109 | expect(calc.getResult()).toBeCloseTo(3.333333, 2); 110 | 111 | calc.divide(2); 112 | expect(calc.getResult()).toBeCloseTo(1.666666, 2); 113 | }); 114 | 115 | test('expression with invalid parentheses', () => { 116 | expect(() => calc.calculate('10 + (2 + 3')).toThrow( 117 | Error 118 | ); 119 | expect(() => calc.calculate('10 + 2) + 3')).toThrow( 120 | Error 121 | ); 122 | expect(() => calc.calculate(')10 + 2(')).toThrow(Error); 123 | }); 124 | }); 125 | -------------------------------------------------------------------------------- /week-2/02-nodejs/tests/todoServer.test.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const { v4: uuidv4 } = require('uuid'); 3 | 4 | const server = require('../todoServer'); 5 | const port = 3000; 6 | const baseUrl = `http://localhost:${port}`; 7 | 8 | describe('Todo API', () => { 9 | let createdTodoId; 10 | let globalServer; 11 | 12 | beforeAll((done) => { 13 | if (globalServer) { 14 | globalServer.close(); 15 | } 16 | globalServer = server.listen(3000); 17 | done() 18 | }); 19 | 20 | afterAll((done) => { 21 | globalServer.close(done); 22 | }); 23 | 24 | const todo = { 25 | title: 'New Todo', 26 | description: 'A new todo item', 27 | }; 28 | 29 | test('should create a new todo item', (done) => { 30 | const options = { 31 | method: 'POST', 32 | headers: { 33 | 'Content-Type': 'application/json', 34 | }, 35 | }; 36 | 37 | const req = http.request(`${baseUrl}/todos`, options, (res) => { 38 | expect(res.statusCode).toBe(201); 39 | let data = ''; 40 | 41 | res.on('data', (chunk) => { 42 | data += chunk; 43 | }); 44 | 45 | res.on('end', () => { 46 | const response = JSON.parse(data); 47 | expect(response.id).toBeTruthy(); 48 | createdTodoId = response.id; 49 | done(); 50 | }); 51 | }); 52 | 53 | req.write(JSON.stringify(todo)); 54 | req.end(); 55 | }); 56 | 57 | test('should retrieve all todo items', (done) => { 58 | http.get(`${baseUrl}/todos`, (res) => { 59 | expect(res.statusCode).toBe(200); 60 | let data = ''; 61 | 62 | res.on('data', (chunk) => { 63 | data += chunk; 64 | }); 65 | 66 | res.on('end', () => { 67 | const todos = JSON.parse(data); 68 | expect(Array.isArray(todos)).toBe(true); 69 | expect(todos.length).toBe(1); 70 | expect(todos[0].title).toBe(todo.title); 71 | expect(todos[0].description).toBe(todo.description); 72 | done(); 73 | }); 74 | }); 75 | }); 76 | 77 | test('should retrieve a specific todo item by ID', (done) => { 78 | http.get(`${baseUrl}/todos/${createdTodoId}`, (res) => { 79 | expect(res.statusCode).toBe(200); 80 | let data = ''; 81 | 82 | res.on('data', (chunk) => { 83 | data += chunk; 84 | }); 85 | 86 | res.on('end', () => { 87 | const todo = JSON.parse(data); 88 | expect(todo.id).toBe(createdTodoId); 89 | done(); 90 | }); 91 | }); 92 | }); 93 | 94 | test('should update a specific todo item', (done) => { 95 | const updatedTodo = { 96 | title: 'Updated Todo', 97 | description: 'An updated todo item', 98 | }; 99 | 100 | const options = { 101 | method: 'PUT', 102 | headers: { 103 | 'Content-Type': 'application/json', 104 | }, 105 | }; 106 | 107 | const req = http.request( 108 | `${baseUrl}/todos/${createdTodoId}`, 109 | options, 110 | (res) => { 111 | expect(res.statusCode).toBe(200); 112 | done(); 113 | } 114 | ); 115 | 116 | req.write(JSON.stringify(updatedTodo)); 117 | req.end(); 118 | }); 119 | 120 | test('should delete a specific todo item', (done) => { 121 | const options = { 122 | method: 'DELETE', 123 | }; 124 | 125 | const req = http.request( 126 | `${baseUrl}/todos/${createdTodoId}`, 127 | options, 128 | (res) => { 129 | expect(res.statusCode).toBe(200); 130 | done(); 131 | } 132 | ); 133 | 134 | req.end(); 135 | }); 136 | 137 | test('should return 404 for a non-existent todo item', (done) => { 138 | http.get(`${baseUrl}/todos/${uuidv4()}`, (res) => { 139 | expect(res.statusCode).toBe(404); 140 | done(); 141 | }); 142 | }); 143 | }); -------------------------------------------------------------------------------- /week-2/02-nodejs/tests/fileServer.test.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | const server = require('../fileServer'); 5 | 6 | describe('API Endpoints', () => { 7 | let globalServer; 8 | 9 | beforeAll((done) => { 10 | if (globalServer) { 11 | globalServer.close(); 12 | } 13 | globalServer = server.listen(3000); 14 | done() 15 | }); 16 | 17 | afterAll((done) => { 18 | globalServer.close(done); 19 | }); 20 | 21 | describe('GET /files', () => { 22 | test('should return a list of files', async () => { 23 | const options = { 24 | method: 'GET', 25 | path: '/files' 26 | }; 27 | const response = await sendRequest(options); 28 | 29 | expect(response.statusCode).toBe(200); 30 | expect(response.body.length).toBeGreaterThan(2); 31 | }); 32 | 33 | test('should handle internal server error', async () => { 34 | const options = { 35 | method: 'GET', 36 | path: '/files' 37 | }; 38 | 39 | const directoryPath = path.resolve(__dirname, '../files/'); 40 | jest 41 | .spyOn(fs, 'readdir') 42 | .mockImplementation((directoryPath, callback) => { 43 | callback(new Error('Mocked Internal Server Error'), null); 44 | }); 45 | 46 | const response = await sendRequest(options); 47 | 48 | expect(response.statusCode).toBe(500); 49 | 50 | fs.readdir.mockRestore(); 51 | }); 52 | }); 53 | 54 | describe('GET /file/:filename', () => { 55 | const testFilePath = path.join(__dirname, '../files', 'test-file.txt'); 56 | 57 | beforeAll(() => { 58 | fs.writeFileSync(testFilePath, 'Test file content'); 59 | }); 60 | 61 | afterAll(() => { 62 | fs.unlinkSync(testFilePath); 63 | }); 64 | 65 | test('should serve the requested file', async () => { 66 | const options = { 67 | method: 'GET', 68 | path: '/file/test-file.txt' 69 | }; 70 | const response = await sendRequest(options); 71 | 72 | expect(response.statusCode).toBe(200); 73 | expect(response.body).toBe('Test file content'); 74 | }); 75 | 76 | test('should handle file not found', async () => { 77 | const options = { 78 | method: 'GET', 79 | path: '/file/non-existing-file.txt' 80 | }; 81 | const response = await sendRequest(options); 82 | 83 | expect(response.statusCode).toBe(404); 84 | expect(response.body).toBe('File not found'); 85 | }); 86 | 87 | }); 88 | 89 | describe('Invalid Routes', () => { 90 | test('should return 404 for invalid routes', async () => { 91 | const options = { 92 | method: 'GET', 93 | path: '/invalid' 94 | }; 95 | const response = await sendRequest(options); 96 | 97 | expect(response.statusCode).toBe(404); 98 | expect(response.body).toBe("Route not found"); 99 | }); 100 | }); 101 | }); 102 | 103 | 104 | 105 | function sendRequest(options, requestBody) { 106 | return new Promise((resolve, reject) => { 107 | const req = http.request( 108 | { 109 | ...options, 110 | host: 'localhost', 111 | port: 3000, 112 | }, 113 | (res) => { 114 | let body = ''; 115 | 116 | res.on('data', (chunk) => { 117 | body += chunk; 118 | }); 119 | 120 | res.on('end', () => { 121 | resolve({ 122 | statusCode: res.statusCode, 123 | headers: res.headers, 124 | body, 125 | }); 126 | }); 127 | } 128 | ); 129 | 130 | req.on('error', (err) => { 131 | reject(err); 132 | }); 133 | 134 | if (requestBody) { 135 | req.write(requestBody); 136 | } 137 | 138 | req.end(); 139 | }); 140 | } -------------------------------------------------------------------------------- /week-2/02-nodejs/solutions/todoServer.solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | You need to create an express HTTP server in Node.js which will handle the logic of a todo list app. 3 | - Don't use any database, just store all the data in an array to store the todo list data (in-memory) 4 | - Hard todo: Try to save responses in files, so that even if u exit the app and run it again, the data remains (similar to databases) 5 | Each todo has a title and a description. The title is a string and the description is a string. 6 | Each todo should also get an unique autogenerated id every time it is created 7 | The expected API endpoints are defined below, 8 | 1.GET /todos - Retrieve all todo items 9 | Description: Returns a list of all todo items. 10 | Response: 200 OK with an array of todo items in JSON format. 11 | Example: GET http://localhost:3000/todos 12 | 2.GET /todos/:id - Retrieve a specific todo item by ID 13 | Description: Returns a specific todo item identified by its ID. 14 | Response: 200 OK with the todo item in JSON format if found, or 404 Not Found if not found. 15 | Example: GET http://localhost:3000/todos/123 16 | 3. POST /todos - Create a new todo item 17 | Description: Creates a new todo item. 18 | Request Body: JSON object representing the todo item. 19 | Response: 201 Created with the ID of the created todo item in JSON format. eg: {id: 1} 20 | Example: POST http://localhost:3000/todos 21 | Request Body: { "title": "Buy groceries", "completed": false, description: "I should buy groceries" } 22 | 4. PUT /todos/:id - Update an existing todo item by ID 23 | Description: Updates an existing todo item identified by its ID. 24 | Request Body: JSON object representing the updated todo item. 25 | Response: 200 OK if the todo item was found and updated, or 404 Not Found if not found. 26 | Example: PUT http://localhost:3000/todos/123 27 | Request Body: { "title": "Buy groceries", "completed": true } 28 | 5. DELETE /todos/:id - Delete a todo item by ID 29 | Description: Deletes a todo item identified by its ID. 30 | Response: 200 OK if the todo item was found and deleted, or 404 Not Found if not found. 31 | Example: DELETE http://localhost:3000/todos/123 32 | - For any other route not defined in the server return 404 33 | Testing the server - run `npm run test-todoServer` command in terminal 34 | */ 35 | const express = require('express'); 36 | const bodyParser = require('body-parser'); 37 | 38 | const app = express(); 39 | 40 | app.use(bodyParser.json()); 41 | 42 | let todos = []; 43 | 44 | app.get('/todos', (req, res) => { 45 | res.json(todos); 46 | }); 47 | 48 | app.get('/todos/:id', (req, res) => { 49 | const todo = todos.find(t => t.id === parseInt(req.params.id)); 50 | if (!todo) { 51 | res.status(404).send(); 52 | } else { 53 | res.json(todo); 54 | } 55 | }); 56 | 57 | app.post('/todos', (req, res) => { 58 | const newTodo = { 59 | id: Math.floor(Math.random() * 1000000), // unique random id 60 | title: req.body.title, 61 | description: req.body.description 62 | }; 63 | todos.push(newTodo); 64 | res.status(201).json(newTodo); 65 | }); 66 | 67 | app.put('/todos/:id', (req, res) => { 68 | const todoIndex = todos.findIndex(t => t.id === parseInt(req.params.id)); 69 | if (todoIndex === -1) { 70 | res.status(404).send(); 71 | } else { 72 | todos[todoIndex].title = req.body.title; 73 | todos[todoIndex].description = req.body.description; 74 | res.json(todos[todoIndex]); 75 | } 76 | }); 77 | 78 | app.delete('/todos/:id', (req, res) => { 79 | const todoIndex = todos.findIndex(t => t.id === parseInt(req.params.id)); 80 | if (todoIndex === -1) { 81 | res.status(404).send(); 82 | } else { 83 | todos.splice(todoIndex, 1); 84 | res.status(200).send(); 85 | } 86 | }); 87 | 88 | // for all other routes, return 404 89 | app.use((req, res, next) => { 90 | res.status(404).send(); 91 | }); 92 | 93 | module.exports = app; -------------------------------------------------------------------------------- /week-3/02-jwt/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": "./", /* 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": "./", /* 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 | -------------------------------------------------------------------------------- /week-3/01-middlewares/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": "./", /* 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": "./", /* 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 | -------------------------------------------------------------------------------- /week-3/02-jwt/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "02-jwt", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "02-jwt", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "jsonwebtoken": "^9.0.2", 13 | "zod": "^3.22.4" 14 | } 15 | }, 16 | "node_modules/buffer-equal-constant-time": { 17 | "version": "1.0.1", 18 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 19 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" 20 | }, 21 | "node_modules/ecdsa-sig-formatter": { 22 | "version": "1.0.11", 23 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 24 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 25 | "dependencies": { 26 | "safe-buffer": "^5.0.1" 27 | } 28 | }, 29 | "node_modules/jsonwebtoken": { 30 | "version": "9.0.2", 31 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", 32 | "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", 33 | "dependencies": { 34 | "jws": "^3.2.2", 35 | "lodash.includes": "^4.3.0", 36 | "lodash.isboolean": "^3.0.3", 37 | "lodash.isinteger": "^4.0.4", 38 | "lodash.isnumber": "^3.0.3", 39 | "lodash.isplainobject": "^4.0.6", 40 | "lodash.isstring": "^4.0.1", 41 | "lodash.once": "^4.0.0", 42 | "ms": "^2.1.1", 43 | "semver": "^7.5.4" 44 | }, 45 | "engines": { 46 | "node": ">=12", 47 | "npm": ">=6" 48 | } 49 | }, 50 | "node_modules/jwa": { 51 | "version": "1.4.1", 52 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 53 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 54 | "dependencies": { 55 | "buffer-equal-constant-time": "1.0.1", 56 | "ecdsa-sig-formatter": "1.0.11", 57 | "safe-buffer": "^5.0.1" 58 | } 59 | }, 60 | "node_modules/jws": { 61 | "version": "3.2.2", 62 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 63 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 64 | "dependencies": { 65 | "jwa": "^1.4.1", 66 | "safe-buffer": "^5.0.1" 67 | } 68 | }, 69 | "node_modules/lodash.includes": { 70 | "version": "4.3.0", 71 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 72 | "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" 73 | }, 74 | "node_modules/lodash.isboolean": { 75 | "version": "3.0.3", 76 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 77 | "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" 78 | }, 79 | "node_modules/lodash.isinteger": { 80 | "version": "4.0.4", 81 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 82 | "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" 83 | }, 84 | "node_modules/lodash.isnumber": { 85 | "version": "3.0.3", 86 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 87 | "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" 88 | }, 89 | "node_modules/lodash.isplainobject": { 90 | "version": "4.0.6", 91 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 92 | "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" 93 | }, 94 | "node_modules/lodash.isstring": { 95 | "version": "4.0.1", 96 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 97 | "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" 98 | }, 99 | "node_modules/lodash.once": { 100 | "version": "4.1.1", 101 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 102 | "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" 103 | }, 104 | "node_modules/lru-cache": { 105 | "version": "6.0.0", 106 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 107 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 108 | "dependencies": { 109 | "yallist": "^4.0.0" 110 | }, 111 | "engines": { 112 | "node": ">=10" 113 | } 114 | }, 115 | "node_modules/ms": { 116 | "version": "2.1.3", 117 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 118 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 119 | }, 120 | "node_modules/safe-buffer": { 121 | "version": "5.2.1", 122 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 123 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 124 | "funding": [ 125 | { 126 | "type": "github", 127 | "url": "https://github.com/sponsors/feross" 128 | }, 129 | { 130 | "type": "patreon", 131 | "url": "https://www.patreon.com/feross" 132 | }, 133 | { 134 | "type": "consulting", 135 | "url": "https://feross.org/support" 136 | } 137 | ] 138 | }, 139 | "node_modules/semver": { 140 | "version": "7.5.4", 141 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", 142 | "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", 143 | "dependencies": { 144 | "lru-cache": "^6.0.0" 145 | }, 146 | "bin": { 147 | "semver": "bin/semver.js" 148 | }, 149 | "engines": { 150 | "node": ">=10" 151 | } 152 | }, 153 | "node_modules/yallist": { 154 | "version": "4.0.0", 155 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 156 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 157 | }, 158 | "node_modules/zod": { 159 | "version": "3.22.4", 160 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", 161 | "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", 162 | "funding": { 163 | "url": "https://github.com/sponsors/colinhacks" 164 | } 165 | } 166 | }, 167 | "dependencies": { 168 | "buffer-equal-constant-time": { 169 | "version": "1.0.1", 170 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 171 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" 172 | }, 173 | "ecdsa-sig-formatter": { 174 | "version": "1.0.11", 175 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 176 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 177 | "requires": { 178 | "safe-buffer": "^5.0.1" 179 | } 180 | }, 181 | "jsonwebtoken": { 182 | "version": "9.0.2", 183 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", 184 | "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", 185 | "requires": { 186 | "jws": "^3.2.2", 187 | "lodash.includes": "^4.3.0", 188 | "lodash.isboolean": "^3.0.3", 189 | "lodash.isinteger": "^4.0.4", 190 | "lodash.isnumber": "^3.0.3", 191 | "lodash.isplainobject": "^4.0.6", 192 | "lodash.isstring": "^4.0.1", 193 | "lodash.once": "^4.0.0", 194 | "ms": "^2.1.1", 195 | "semver": "^7.5.4" 196 | } 197 | }, 198 | "jwa": { 199 | "version": "1.4.1", 200 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 201 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 202 | "requires": { 203 | "buffer-equal-constant-time": "1.0.1", 204 | "ecdsa-sig-formatter": "1.0.11", 205 | "safe-buffer": "^5.0.1" 206 | } 207 | }, 208 | "jws": { 209 | "version": "3.2.2", 210 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 211 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 212 | "requires": { 213 | "jwa": "^1.4.1", 214 | "safe-buffer": "^5.0.1" 215 | } 216 | }, 217 | "lodash.includes": { 218 | "version": "4.3.0", 219 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 220 | "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" 221 | }, 222 | "lodash.isboolean": { 223 | "version": "3.0.3", 224 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 225 | "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" 226 | }, 227 | "lodash.isinteger": { 228 | "version": "4.0.4", 229 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 230 | "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" 231 | }, 232 | "lodash.isnumber": { 233 | "version": "3.0.3", 234 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 235 | "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" 236 | }, 237 | "lodash.isplainobject": { 238 | "version": "4.0.6", 239 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 240 | "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" 241 | }, 242 | "lodash.isstring": { 243 | "version": "4.0.1", 244 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 245 | "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" 246 | }, 247 | "lodash.once": { 248 | "version": "4.1.1", 249 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 250 | "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" 251 | }, 252 | "lru-cache": { 253 | "version": "6.0.0", 254 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 255 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 256 | "requires": { 257 | "yallist": "^4.0.0" 258 | } 259 | }, 260 | "ms": { 261 | "version": "2.1.3", 262 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 263 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 264 | }, 265 | "safe-buffer": { 266 | "version": "5.2.1", 267 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 268 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 269 | }, 270 | "semver": { 271 | "version": "7.5.4", 272 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", 273 | "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", 274 | "requires": { 275 | "lru-cache": "^6.0.0" 276 | } 277 | }, 278 | "yallist": { 279 | "version": "4.0.0", 280 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 281 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 282 | }, 283 | "zod": { 284 | "version": "3.22.4", 285 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", 286 | "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==" 287 | } 288 | } 289 | } 290 | --------------------------------------------------------------------------------