├── .gitignore ├── 1. node-tutorial ├── 1. hello-world-node │ ├── index.js │ └── sum.js ├── 10. event-emitter │ ├── custom-listener.js │ └── index.js ├── 2. node-module-system │ ├── first-module.js │ ├── index.js │ ├── wrapper-demo.js │ └── wrapper-explorer.js ├── 3. node-package-manager │ ├── index.js │ ├── package-lock.json │ └── package.json ├── 4. path-module │ └── index.js ├── 5. file-system │ ├── data │ │ ├── async-example.txt │ │ └── example.txt │ └── index.js ├── 6. http-module │ ├── routes.js │ └── server.js ├── 7. callbacks │ ├── callback-hell.js │ ├── index.js │ ├── input.txt │ └── output.txt ├── 8. promises │ └── index.js └── 9. async-await │ └── index.js ├── 10. nodejs-graphql ├── 1. basics │ ├── package-lock.json │ ├── package.json │ └── src │ │ ├── data │ │ └── products.js │ │ ├── graphql │ │ ├── resolvers.js │ │ └── schema.js │ │ └── server.js └── 2. mongoose-integration │ ├── package-lock.json │ ├── package.json │ └── src │ ├── data │ └── products.js │ ├── database │ └── db.js │ ├── graphql │ ├── resolvers.js │ └── schema.js │ ├── models │ └── Product.js │ └── server.js ├── 11. nodejs-with-typescript ├── dist │ └── app.js ├── package-lock.json ├── package.json ├── src │ ├── app.ts │ ├── basics.ts │ └── models │ │ └── User.ts └── tsconfig.json ├── 2. express-tutorial ├── app-module.js ├── custom-middleware.js ├── index.js ├── middleware.js ├── package-lock.json ├── package.json └── routes-example.js ├── 3. ejs-tutorial ├── index.js ├── package-lock.json ├── package.json └── views │ ├── about.ejs │ ├── components │ └── header.ejs │ └── home.ejs ├── 4. rest-api-development ├── app.js ├── package-lock.json └── package.json ├── 5. mongodb-basics ├── app.js ├── package-lock.json └── package.json ├── 6. bookstore-api ├── controllers │ └── book-controller.js ├── database │ └── db.js ├── models │ └── book.js ├── package-lock.json ├── package.json ├── routes │ └── book-routes.js └── server.js ├── 7. nodejs-auth ├── .gitignore ├── config │ └── cloudinary.js ├── controllers │ ├── auth-controller.js │ └── image-controller.js ├── database │ └── db.js ├── helpers │ └── cloudinaryHelper.js ├── middleware │ ├── admin-middleware.js │ ├── auth-middleware.js │ └── upload-middleware.js ├── models │ ├── Image.js │ └── User.js ├── package-lock.json ├── package.json ├── routes │ ├── admin-routes.js │ ├── auth-routes.js │ ├── home-routes.js │ └── image-routes.js ├── server.js └── vercel.json ├── 8. mongodb-intermediate ├── controllers │ ├── book-controller.js │ └── product-controller.js ├── models │ ├── Author.js │ ├── Book.js │ └── Product.js ├── package-lock.json ├── package.json ├── routes │ ├── book-routes.js │ └── product-routes.js └── server.js └── 9. nodejs-socket ├── package-lock.json ├── package.json ├── public └── index.html └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /1. node-tutorial/1. hello-world-node/index.js: -------------------------------------------------------------------------------- 1 | console.log("hello js"); 2 | 3 | const array = [1, 2, 3, 4]; 4 | 5 | console.log(array, "array"); 6 | 7 | setTimeout(() => { 8 | console.log("this message is delayed by 2 seconds"); 9 | }, 2000); 10 | 11 | console.log("this is the last line of the sync code"); 12 | -------------------------------------------------------------------------------- /1. node-tutorial/1. hello-world-node/sum.js: -------------------------------------------------------------------------------- 1 | function sum(num1, num2) { 2 | return num1 + num2; 3 | } 4 | 5 | console.log(sum(2, 3)); 6 | -------------------------------------------------------------------------------- /1. node-tutorial/10. event-emitter/custom-listener.js: -------------------------------------------------------------------------------- 1 | const EventEmitter = require("events"); 2 | 3 | class MyCustomEmitter extends EventEmitter { 4 | constructor() { 5 | super(); 6 | this.greeting = "Hello"; 7 | } 8 | 9 | greet(name) { 10 | this.emit("greeting", `${this.greeting}, ${name}`); 11 | } 12 | } 13 | 14 | const myCustomEmitter = new MyCustomEmitter(); 15 | 16 | myCustomEmitter.on("greeting", (input) => { 17 | console.log(`Greeting event`, input); 18 | }); 19 | 20 | myCustomEmitter.greet("Sangam Mukherjee"); 21 | -------------------------------------------------------------------------------- /1. node-tutorial/10. event-emitter/index.js: -------------------------------------------------------------------------------- 1 | const EventEmitter = require("events"); 2 | 3 | const myFirstEmitter = new EventEmitter(); 4 | 5 | //register a listener 6 | myFirstEmitter.on("greet", (name) => { 7 | console.log(`Hello ${name}`); 8 | }); 9 | 10 | myFirstEmitter.emit("greet", "Sangam Mukherjee"); 11 | -------------------------------------------------------------------------------- /1. node-tutorial/2. node-module-system/first-module.js: -------------------------------------------------------------------------------- 1 | function add(a, b) { 2 | return a + b; 3 | } 4 | 5 | function substract(a, b) { 6 | return a - b; 7 | } 8 | 9 | function divide(a, b) { 10 | if (b === 0) { 11 | throw new Error("Divide by zero is not allowed"); 12 | } 13 | 14 | return a / b; 15 | } 16 | 17 | module.exports = { 18 | add, 19 | substract, 20 | divide, 21 | }; 22 | -------------------------------------------------------------------------------- /1. node-tutorial/2. node-module-system/index.js: -------------------------------------------------------------------------------- 1 | //module.exports 2 | //require 3 | 4 | const firstModule = require("./first-module"); 5 | 6 | console.log(firstModule.add(10, 20)); 7 | 8 | try { 9 | console.log("trying to divide by zero"); 10 | let result = firstModule.divide(0, 10); 11 | console.log(result, "result"); 12 | } catch (error) { 13 | console.log("Caught an error", error.message); 14 | } 15 | 16 | // //module wrapper 17 | // ( 18 | // function(exports, require, module, __filename, __dirname){ 19 | // //your module code goes here 20 | // } 21 | // ) 22 | -------------------------------------------------------------------------------- /1. node-tutorial/2. node-module-system/wrapper-demo.js: -------------------------------------------------------------------------------- 1 | const wrapperExplorer = require("./wrapper-explorer"); 2 | 3 | console.log(`in wrapper demo.js file`); 4 | 5 | console.log("__filename in wrapper demo", __filename); 6 | console.log("__dirname in wrapper demo", __dirname); 7 | 8 | wrapperExplorer.greet("Sangam Mukherjee"); 9 | -------------------------------------------------------------------------------- /1. node-tutorial/2. node-module-system/wrapper-explorer.js: -------------------------------------------------------------------------------- 1 | console.log("Node module wrapper demo"); 2 | 3 | console.log("__filename in wrapper explorer", __filename); 4 | console.log("__dirname in wrapper explorer", __dirname); 5 | 6 | module.exports.greet = function (name) { 7 | console.log(`Hello ${name}`); 8 | }; 9 | -------------------------------------------------------------------------------- /1. node-tutorial/3. node-package-manager/index.js: -------------------------------------------------------------------------------- 1 | const lodash = require("lodash"); 2 | 3 | const names = ["sangam", "john", "terry", "alex", "mia"]; 4 | const capitalize = lodash.map(names, lodash.capitalize); 5 | 6 | console.log(capitalize); 7 | -------------------------------------------------------------------------------- /1. node-tutorial/3. node-package-manager/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3.-node-package-manager", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "3.-node-package-manager", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "lodash": "^4.17.21" 13 | } 14 | }, 15 | "node_modules/lodash": { 16 | "version": "4.17.21", 17 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 18 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /1. node-tutorial/3. node-package-manager/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3.-node-package-manager", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /1. node-tutorial/4. path-module/index.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | console.log("Directory name:", path.dirname(__filename)); 4 | 5 | console.log("File name", path.basename(__filename)); 6 | 7 | console.log("file extension", path.extname(__filename)); 8 | 9 | const joinPath = path.join("/user", "documents", "node", "projects"); 10 | console.log("Joined path", joinPath); 11 | 12 | const resolvePath = path.resolve("user", "documents", "node", "project"); 13 | console.log("Resolve path:", resolvePath); 14 | 15 | const normalizePath = path.normalize("/user/.documents/../node/projects"); 16 | console.log("normalizePath", normalizePath); 17 | -------------------------------------------------------------------------------- /1. node-tutorial/5. file-system/data/async-example.txt: -------------------------------------------------------------------------------- 1 | Hello, Async node js 2 | This ia another line added -------------------------------------------------------------------------------- /1. node-tutorial/5. file-system/data/example.txt: -------------------------------------------------------------------------------- 1 | Hello from node js 2 | This is a new line added to that file -------------------------------------------------------------------------------- /1. node-tutorial/5. file-system/index.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const dataFolder = path.join(__dirname, "data"); 5 | 6 | if (!fs.existsSync(dataFolder)) { 7 | fs.mkdirSync(dataFolder); 8 | console.log("data folder created"); 9 | } 10 | 11 | const filePath = path.join(dataFolder, "example.txt"); 12 | //sync way of creating the file 13 | fs.writeFileSync(filePath, "Hello from node js"); 14 | console.log("file created successfully"); 15 | 16 | const readContentFromFile = fs.readFileSync(filePath, "utf8"); 17 | console.log("File content:", readContentFromFile); 18 | 19 | fs.appendFileSync(filePath, "\nThis is a new line added to that file"); 20 | console.log("new file content added"); 21 | 22 | //async way of creating the file 23 | const asyncFilePath = path.join(dataFolder, "async-example.txt"); 24 | fs.writeFile(asyncFilePath, "Hello, Async node js", (err) => { 25 | if (err) throw err; 26 | console.log("Async file is created successfully"); 27 | 28 | fs.readFile(asyncFilePath, "utf8", (err, data) => { 29 | if (err) throw err; 30 | console.log("Async file content:", data); 31 | 32 | fs.appendFile(asyncFilePath, "\nThis ia another line added", (err) => { 33 | if (err) throw err; 34 | console.log("New line added to async file"); 35 | 36 | fs.readFile(asyncFilePath, "utf8", (err, updatedData) => { 37 | if (err) throw err; 38 | console.log("Updated file content", updatedData); 39 | }); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /1. node-tutorial/6. http-module/routes.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | const server = http.createServer((req, res) => { 3 | const url = req.url; 4 | if (url === "/") { 5 | res.writeHead(200, { "Content-Type": "text/plain" }); 6 | res.end("Home page"); 7 | } else if (url === "/projects") { 8 | res.writeHead(200, { "Content-Type": "text/plain" }); 9 | res.end("Projects"); 10 | } else { 11 | res.writeHead(404, { "Content-Type": "text/plain" }); 12 | res.end("This page can not be found!"); 13 | } 14 | }); 15 | 16 | const port = 3000; 17 | server.listen(port, () => { 18 | console.log(`Server is now listening to port ${port}`); 19 | }); 20 | -------------------------------------------------------------------------------- /1. node-tutorial/6. http-module/server.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | 3 | const server = http.createServer((req, res) => { 4 | console.log(req, "req"); 5 | res.writeHead(200, { "Content-Type": "text/plain" }); 6 | res.end("Hello node js from http module"); 7 | }); 8 | 9 | const port = 3000; 10 | server.listen(port, () => { 11 | console.log(`Server is now listening to port ${port}`); 12 | }); 13 | -------------------------------------------------------------------------------- /1. node-tutorial/7. callbacks/callback-hell.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | fs.readFile("input.txt", "utf8", (err, data) => { 4 | if (err) { 5 | console.error("Error reading file", err); 6 | return; 7 | } 8 | 9 | const modifyFileData = data.toUpperCase(); 10 | 11 | fs.writeFile("output.txt", modifyFileData, (err) => { 12 | if (err) { 13 | console.error("Error writing file", err); 14 | return; 15 | } 16 | 17 | console.log("data written to the new file"); 18 | 19 | fs.readFile("output.txt", "utf8", (err, data) => { 20 | if (err) { 21 | console.error("Error reading file", err); 22 | return; 23 | } 24 | 25 | console.log(data); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /1. node-tutorial/7. callbacks/index.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | function person(name, callbackFn) { 4 | console.log(`Hello ${name}`); 5 | callbackFn(); 6 | } 7 | 8 | function address() { 9 | console.log("India"); 10 | } 11 | 12 | person("Sangam Mukherjee", address); 13 | 14 | fs.readFile("input.txt", "utf8", (err, data) => { 15 | if (err) { 16 | console.error("Error reading file", err); 17 | return; 18 | } 19 | 20 | console.log(data); 21 | }); 22 | -------------------------------------------------------------------------------- /1. node-tutorial/7. callbacks/input.txt: -------------------------------------------------------------------------------- 1 | callback logic concepts -------------------------------------------------------------------------------- /1. node-tutorial/7. callbacks/output.txt: -------------------------------------------------------------------------------- 1 | CALLBACK LOGIC CONCEPTS -------------------------------------------------------------------------------- /1. node-tutorial/8. promises/index.js: -------------------------------------------------------------------------------- 1 | function delayFn(time) { 2 | return new Promise((resolve) => setTimeout(resolve, time)); 3 | } 4 | 5 | console.log("Promise lecture starts"); 6 | delayFn(200).then(() => console.log("after 2 seconds promise resolved")); 7 | console.log("end"); 8 | 9 | function divideFn(num1, num2) { 10 | return new Promise((resolve, reject) => { 11 | if (num2 === 0) { 12 | reject("Can not perform division by 0"); 13 | } else { 14 | resolve(num1 / num2); 15 | } 16 | }); 17 | } 18 | 19 | divideFn(10, 0) 20 | .then((result) => console.log(result, "res")) 21 | .catch((error) => console.log(error, "err")); 22 | -------------------------------------------------------------------------------- /1. node-tutorial/9. async-await/index.js: -------------------------------------------------------------------------------- 1 | function delayFn(time) { 2 | return new Promise((resolve) => setTimeout(resolve, time)); 3 | } 4 | 5 | async function delayedGreet(name) { 6 | await delayFn(2000); 7 | console.log(name); 8 | } 9 | 10 | delayedGreet("Sangam"); 11 | 12 | async function division(num1, num2) { 13 | try { 14 | if (num2 === 0) throw new Error("Can not divide by 0"); 15 | return num1 / num2; 16 | } catch (error) { 17 | console.error("error", error); 18 | return null; 19 | } 20 | } 21 | 22 | async function mainFn() { 23 | console.log(await division(10, 2)); 24 | console.log(await division(10, 0)); 25 | } 26 | 27 | mainFn(); 28 | -------------------------------------------------------------------------------- /10. nodejs-graphql/1. basics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10.-nodejs-graphql", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node src/server.js", 9 | "dev": "nodemon src/server.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@apollo/server": "^4.11.0", 16 | "graphql": "^16.9.0", 17 | "graphql-tag": "^2.12.6" 18 | }, 19 | "devDependencies": { 20 | "nodemon": "^3.1.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /10. nodejs-graphql/1. basics/src/data/products.js: -------------------------------------------------------------------------------- 1 | const products = [ 2 | { 3 | id: "1", 4 | title: "Laptop", 5 | category: "Electronics", 6 | price: 990.95, 7 | inStock: true, 8 | }, 9 | { 10 | id: "2", 11 | title: "Coffee", 12 | category: "Food", 13 | price: 50.95, 14 | inStock: true, 15 | }, 16 | { 17 | id: "3", 18 | title: "Shoes", 19 | category: "Sports", 20 | price: 1990.95, 21 | inStock: false, 22 | }, 23 | ]; 24 | 25 | module.exports = products; 26 | -------------------------------------------------------------------------------- /10. nodejs-graphql/1. basics/src/graphql/resolvers.js: -------------------------------------------------------------------------------- 1 | const products = require("../data/products"); 2 | 3 | const resolvers = { 4 | Query: { 5 | products: () => products, 6 | product: (_, { id }) => products.find((item) => item.id === id), 7 | }, 8 | 9 | Mutation: { 10 | createProduct: (_, { title, category, price, inStock }) => { 11 | const newlyCreatedProduct = { 12 | id: String(products.length + 1), 13 | title, 14 | category, 15 | price, 16 | inStock, 17 | }; 18 | 19 | products.push(newlyCreatedProduct); 20 | return newlyCreatedProduct; 21 | }, 22 | 23 | deleteProduct: (_, { id }) => { 24 | const index = products.findIndex((product) => product.id === id); 25 | if (index === -1) return false; 26 | 27 | products.splice(index, 1); 28 | 29 | return true; 30 | }, 31 | 32 | updateProduct: (_, { id, ...updates }) => { 33 | const index = products.findIndex((product) => product.id === id); 34 | if (index === -1) return null; 35 | 36 | const updatedProduct = { 37 | ...products[index], 38 | ...updates, 39 | }; 40 | 41 | products[index] = updatedProduct; 42 | 43 | return updatedProduct; 44 | }, 45 | }, 46 | }; 47 | 48 | module.exports = resolvers; 49 | -------------------------------------------------------------------------------- /10. nodejs-graphql/1. basics/src/graphql/schema.js: -------------------------------------------------------------------------------- 1 | //this file will tell that what will be the structure of your data 2 | 3 | const { gql } = require("graphql-tag"); 4 | 5 | //String 6 | //Int 7 | //Float 8 | //Boolean 9 | //ID -> an unique identifier 10 | 11 | // -> blog -> fetch all the blogs, fetch blog by id 12 | 13 | // req.params.id -> /api/product/12345 14 | 15 | // req.body 16 | 17 | const typeDefs = gql` 18 | type Product { 19 | id: ID! 20 | title: String! 21 | category: String! 22 | price: Float! 23 | inStock: Boolean! 24 | } 25 | 26 | type Query { 27 | products: [Product!]! 28 | product(id: ID!): Product 29 | } 30 | 31 | type Mutation { 32 | createProduct( 33 | title: String! 34 | category: String! 35 | price: Float! 36 | inStock: Boolean! 37 | ): Product 38 | deleteProduct(id: ID!): Boolean 39 | updateProduct( 40 | id: ID! 41 | title: String 42 | category: String 43 | price: Float 44 | inStock: Boolean 45 | ): Product 46 | } 47 | `; 48 | 49 | module.exports = typeDefs; 50 | -------------------------------------------------------------------------------- /10. nodejs-graphql/1. basics/src/server.js: -------------------------------------------------------------------------------- 1 | const { ApolloServer } = require("@apollo/server"); 2 | const { startStandaloneServer } = require("@apollo/server/standalone"); 3 | const typeDefs = require("./graphql/schema"); 4 | const resolvers = require("./graphql/resolvers"); 5 | 6 | async function startServer() { 7 | const server = new ApolloServer({ 8 | typeDefs, 9 | resolvers, 10 | }); 11 | 12 | const { url } = await startStandaloneServer(server, { 13 | listen: { port: 4000 }, 14 | }); 15 | 16 | console.log(`Server ready at: ${url}`); 17 | } 18 | 19 | startServer(); 20 | -------------------------------------------------------------------------------- /10. nodejs-graphql/2. mongoose-integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10.-nodejs-graphql", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node src/server.js", 9 | "dev": "nodemon src/server.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@apollo/server": "^4.11.0", 16 | "dotenv": "^16.4.5", 17 | "graphql": "^16.9.0", 18 | "graphql-tag": "^2.12.6", 19 | "mongoose": "^8.7.3" 20 | }, 21 | "devDependencies": { 22 | "nodemon": "^3.1.7" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /10. nodejs-graphql/2. mongoose-integration/src/data/products.js: -------------------------------------------------------------------------------- 1 | const products = [ 2 | { 3 | id: "1", 4 | title: "Laptop", 5 | category: "Electronics", 6 | price: 990.95, 7 | inStock: true, 8 | }, 9 | { 10 | id: "2", 11 | title: "Coffee", 12 | category: "Food", 13 | price: 50.95, 14 | inStock: true, 15 | }, 16 | { 17 | id: "3", 18 | title: "Shoes", 19 | category: "Sports", 20 | price: 1990.95, 21 | inStock: false, 22 | }, 23 | ]; 24 | 25 | module.exports = products; 26 | -------------------------------------------------------------------------------- /10. nodejs-graphql/2. mongoose-integration/src/database/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const connectDB = async () => { 4 | try { 5 | await mongoose.connect(process.env.MONGO_URI); 6 | console.log("Mongodb connected successfully"); 7 | } catch (e) { 8 | console.error("Mongo connection failed!", e); 9 | process.exit(1); 10 | } 11 | }; 12 | 13 | module.exports = connectDB; 14 | -------------------------------------------------------------------------------- /10. nodejs-graphql/2. mongoose-integration/src/graphql/resolvers.js: -------------------------------------------------------------------------------- 1 | const Product = require("../models/Product"); 2 | 3 | const resolvers = { 4 | Query: { 5 | products: async () => await Product.find({}), 6 | product: async (_, { id }) => await Product.findById(id), 7 | }, 8 | 9 | Mutation: { 10 | createProduct: async (_, args) => { 11 | const newlyCreatedProduct = new Product(args); 12 | 13 | return await newlyCreatedProduct.save(); 14 | }, 15 | 16 | updateProduct: async (_, { id, ...updatedFields }) => { 17 | return await Product.findByIdAndUpdate(id, updatedFields, { new: true }); 18 | }, 19 | 20 | deleteProduct: async (_, { id }) => { 21 | const deletedProduct = await Product.findByIdAndDelete(id); 22 | 23 | return !!deletedProduct; 24 | }, 25 | }, 26 | }; 27 | 28 | module.exports = resolvers; 29 | -------------------------------------------------------------------------------- /10. nodejs-graphql/2. mongoose-integration/src/graphql/schema.js: -------------------------------------------------------------------------------- 1 | //this file will tell that what will be the structure of your data 2 | 3 | const { gql } = require("graphql-tag"); 4 | 5 | //String 6 | //Int 7 | //Float 8 | //Boolean 9 | //ID -> an unique identifier 10 | 11 | // -> blog -> fetch all the blogs, fetch blog by id 12 | 13 | // req.params.id -> /api/product/12345 14 | 15 | // req.body 16 | 17 | const typeDefs = gql` 18 | type Product { 19 | id: ID! 20 | title: String! 21 | category: String! 22 | price: Float! 23 | inStock: Boolean! 24 | } 25 | 26 | type Query { 27 | products: [Product!]! 28 | product(id: ID!): Product 29 | } 30 | 31 | type Mutation { 32 | createProduct( 33 | title: String! 34 | category: String! 35 | price: Float! 36 | inStock: Boolean! 37 | ): Product 38 | deleteProduct(id: ID!): Boolean 39 | updateProduct( 40 | id: ID! 41 | title: String 42 | category: String 43 | price: Float 44 | inStock: Boolean 45 | ): Product 46 | } 47 | `; 48 | 49 | module.exports = typeDefs; 50 | -------------------------------------------------------------------------------- /10. nodejs-graphql/2. mongoose-integration/src/models/Product.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const ProductSchema = new mongoose.Schema({ 4 | title: { 5 | type: String, 6 | required: true, 7 | }, 8 | category: { 9 | type: String, 10 | required: true, 11 | }, 12 | price: { 13 | type: Number, 14 | required: true, 15 | }, 16 | inStock: { 17 | type: Boolean, 18 | required: true, 19 | }, 20 | }); 21 | 22 | module.exports = mongoose.model("product", ProductSchema); 23 | -------------------------------------------------------------------------------- /10. nodejs-graphql/2. mongoose-integration/src/server.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const { ApolloServer } = require("@apollo/server"); 3 | const { startStandaloneServer } = require("@apollo/server/standalone"); 4 | const connectDB = require("./database/db"); 5 | const typeDefs = require("./graphql/schema"); 6 | const resolvers = require("./graphql/resolvers"); 7 | 8 | async function startServer() { 9 | await connectDB(); 10 | const server = new ApolloServer({ 11 | typeDefs, 12 | resolvers, 13 | }); 14 | 15 | const { url } = await startStandaloneServer(server, { 16 | listen: { port: process.env.PORT }, 17 | }); 18 | 19 | console.log(`Server ready at: ${url}`); 20 | } 21 | 22 | startServer(); 23 | -------------------------------------------------------------------------------- /11. nodejs-with-typescript/dist/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | console.log("Hello Node js from typescript"); 3 | function getName(name) { 4 | return name; 5 | } 6 | console.log(getName("Sangam")); 7 | -------------------------------------------------------------------------------- /11. nodejs-with-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "11.-nodejs-with-typescript", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "tsc", 8 | "start": "node dist/app.js", 9 | "dev": "nodemon src/app.ts" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "@types/mongoose": "^5.11.97", 16 | "@types/node": "^22.8.2", 17 | "ts-node": "^10.9.2", 18 | "typescript": "^5.6.3" 19 | }, 20 | "dependencies": { 21 | "@types/express": "^5.0.0", 22 | "express": "^4.21.1", 23 | "mongoose": "^8.7.3", 24 | "nodemon": "^3.1.7" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /11. nodejs-with-typescript/src/app.ts: -------------------------------------------------------------------------------- 1 | import express, { Express, Request, Response, NextFunction } from "express"; 2 | import { IUser, User } from "./models/User"; 3 | 4 | const app: Express = express(); 5 | const port = 3000; 6 | 7 | app.use(express.json()); 8 | 9 | interface CustomRequest extends Request { 10 | startTime?: number; 11 | } 12 | 13 | //middleware -> add startTime to request 14 | app.use((req: CustomRequest, res: Response, next: NextFunction) => { 15 | req.startTime = Date.now(); 16 | next(); 17 | }); 18 | 19 | app.get("/", (req: Request, res: Response) => { 20 | res.send("Hello. Typescript with express"); 21 | }); 22 | 23 | app.get("/users", async (req: Request, res: Response) => { 24 | try { 25 | const users: IUser[] = await User.find(); 26 | } catch (e) { 27 | res.status(400).json({ message: "Some error occured!" }); 28 | } 29 | }); 30 | 31 | //post route -> new user -> name, email -> req.body 32 | // -> /user/:id?name -> Request <{}, {}, {},{}> 33 | 34 | interface User { 35 | name: string; 36 | email: string; 37 | } 38 | 39 | app.post("/user", (req: Request<{}, {}, User>, res: Response) => { 40 | const { name, email } = req.body; 41 | res.json({ 42 | message: `User created ${name}-${email}`, 43 | }); 44 | }); 45 | 46 | //users based on id 47 | app.get("/users/:id", (req: Request<{ id: string }>, res: Response) => { 48 | const { id } = req.params; 49 | res.json({ 50 | userId: id, 51 | }); 52 | }); 53 | 54 | app.listen(port, () => { 55 | console.log(`Server is now running on port ${port}`); 56 | }); 57 | -------------------------------------------------------------------------------- /11. nodejs-with-typescript/src/basics.ts: -------------------------------------------------------------------------------- 1 | console.log("Hello Node js from typescript"); 2 | 3 | //basic types 4 | 5 | let isDone: Boolean = false; 6 | 7 | let num: number = 100; 8 | 9 | let str: string = "Sangam"; 10 | 11 | let list: number[] = [1, 2, 3]; 12 | let products: Array = ["product 1", "product 2", "product 3"]; 13 | 14 | let randomVal: any = 4; 15 | 16 | randomVal = "sangam"; 17 | randomVal = true; 18 | randomVal = []; 19 | 20 | let xyz: undefined = undefined; 21 | let yz: null = null; 22 | 23 | enum Color { 24 | Red, 25 | Green, 26 | Blue, 27 | } 28 | 29 | let d: Color = Color.Green; 30 | 31 | //tuple 32 | 33 | let abc: [string, number] = ["hi", 400]; 34 | 35 | //interfaces, types 36 | 37 | interface User { 38 | name: String; 39 | id: number; 40 | email?: string; //optional 41 | readonly createdAt: Date; 42 | } 43 | 44 | const user: User = { 45 | name: "Sangam", 46 | id: 1, 47 | createdAt: new Date(), 48 | email: "abc@gmail.com", 49 | }; 50 | 51 | type Product = { 52 | title: string; 53 | price: number; 54 | }; 55 | 56 | const product1: Product = { 57 | title: "Product 1", 58 | price: 200, 59 | }; 60 | 61 | //functions with type annotations 62 | 63 | function multiply(a: number, b: number): number { 64 | return a * b; 65 | } 66 | 67 | const add = (num1: number, num2: number): number => { 68 | return num1 + num2; 69 | }; 70 | 71 | function greet(name: string, greeting?: string): string { 72 | return `${name} ${greeting}`; 73 | } 74 | 75 | console.log(greet("sangam", "hello")); 76 | -------------------------------------------------------------------------------- /11. nodejs-with-typescript/src/models/User.ts: -------------------------------------------------------------------------------- 1 | import mongoose, { Schema, Document } from "mongoose"; 2 | 3 | interface IUser extends Document { 4 | name: string; 5 | email: string; 6 | age: number; 7 | createdAt: Date; 8 | } 9 | 10 | const UserSchema = new Schema({ 11 | name: String, 12 | email: String, 13 | age: Number, 14 | createdAt: Date, 15 | }); 16 | 17 | const User = mongoose.model("User", UserSchema); 18 | 19 | export { User, IUser }; 20 | -------------------------------------------------------------------------------- /11. nodejs-with-typescript/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": [ 16 | "es6" 17 | ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, 18 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 19 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 20 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 21 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 22 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 23 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 24 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 25 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 26 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 27 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 28 | 29 | /* Modules */ 30 | "module": "commonjs" /* Specify what module code is generated. */, 31 | "rootDir": "./src" /* Specify the root folder within your source files. */, 32 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 33 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 34 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 35 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 36 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 37 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 38 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 39 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 40 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 41 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 42 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 43 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 44 | // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ 45 | // "resolveJsonModule": true, /* Enable importing .json files. */ 46 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 47 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 48 | 49 | /* JavaScript Support */ 50 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 51 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 52 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 53 | 54 | /* Emit */ 55 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 56 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 57 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 58 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 59 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 60 | // "noEmit": true, /* Disable emitting files from a compilation. */ 61 | // "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. */ 62 | "outDir": "./dist" /* Specify an output folder for all emitted files. */, 63 | // "removeComments": true, /* Disable emitting comments. */ 64 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 65 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 66 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 67 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 68 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 69 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 70 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 71 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 72 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 73 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 74 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 75 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 76 | 77 | /* Interop Constraints */ 78 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 79 | // "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. */ 80 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ 81 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 82 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, 83 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 84 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 85 | 86 | /* Type Checking */ 87 | "strict": true /* Enable all strict type-checking options. */, 88 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 89 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 90 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 91 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 92 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 93 | // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ 94 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 95 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 96 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 97 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 98 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 99 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 100 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 101 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 102 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 103 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 104 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 105 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 106 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 107 | 108 | /* Completeness */ 109 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 110 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 111 | }, 112 | "include": ["src/**/*"], 113 | "exclude": ["node_modules"] 114 | } 115 | -------------------------------------------------------------------------------- /2. express-tutorial/app-module.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | 3 | const app = express(); 4 | 5 | //application level settings 6 | app.set("view engine", "ejs"); 7 | 8 | //routing 9 | app.get("/", (req, res) => { 10 | res.send("home page"); 11 | }); 12 | 13 | app.post("/api/data", (req, res) => { 14 | res.json({ 15 | message: "Data received", 16 | data: req.body, 17 | }); 18 | }); 19 | 20 | app.use((err, req, res, next) => { 21 | console.log(err.stack); 22 | res.status(500).send("something went wrong"); 23 | }); 24 | 25 | const port = 3000; 26 | app.listen(port, () => { 27 | console.log(`Server is now running at port ${port}`); 28 | }); 29 | -------------------------------------------------------------------------------- /2. express-tutorial/custom-middleware.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | 4 | const requestTimestampLogger = (req, res, next) => { 5 | const timeStamp = new Date().toISOString(); 6 | 7 | console.log(`${timeStamp} from ${req.method} to ${req.url}`); 8 | next(); 9 | }; 10 | 11 | app.use(requestTimestampLogger); 12 | 13 | app.get("/", (req, res) => { 14 | res.send("Home page"); 15 | }); 16 | 17 | app.get("/about", (req, res) => { 18 | res.send("About page"); 19 | }); 20 | 21 | app.listen(3000, () => { 22 | console.log(`Server is now running on port 3000`); 23 | }); 24 | -------------------------------------------------------------------------------- /2. express-tutorial/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | 3 | const app = express(); 4 | 5 | app.get("/", (req, res) => { 6 | res.send("Hello world"); 7 | }); 8 | 9 | const port = 3000; 10 | app.listen(port, () => { 11 | console.log(`Server is now running at port ${port}`); 12 | }); 13 | -------------------------------------------------------------------------------- /2. express-tutorial/middleware.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | 4 | //define middleware function 5 | const myFirstMiddleware = (req, res, next) => { 6 | console.log("this first middleware will run on every request"); 7 | 8 | next(); 9 | }; 10 | 11 | app.use(myFirstMiddleware); 12 | 13 | app.get("/", (req, res) => { 14 | res.send("Home page"); 15 | }); 16 | 17 | app.get("/about", (req, res) => { 18 | res.send("About page"); 19 | }); 20 | 21 | app.listen(3000, () => { 22 | console.log(`Server is now running on port 3000`); 23 | }); 24 | -------------------------------------------------------------------------------- /2. express-tutorial/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2.-express-tutorial", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "2.-express-tutorial", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.21.0" 13 | } 14 | }, 15 | "node_modules/accepts": { 16 | "version": "1.3.8", 17 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 18 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 19 | "dependencies": { 20 | "mime-types": "~2.1.34", 21 | "negotiator": "0.6.3" 22 | }, 23 | "engines": { 24 | "node": ">= 0.6" 25 | } 26 | }, 27 | "node_modules/array-flatten": { 28 | "version": "1.1.1", 29 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 30 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 31 | }, 32 | "node_modules/body-parser": { 33 | "version": "1.20.3", 34 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 35 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 36 | "dependencies": { 37 | "bytes": "3.1.2", 38 | "content-type": "~1.0.5", 39 | "debug": "2.6.9", 40 | "depd": "2.0.0", 41 | "destroy": "1.2.0", 42 | "http-errors": "2.0.0", 43 | "iconv-lite": "0.4.24", 44 | "on-finished": "2.4.1", 45 | "qs": "6.13.0", 46 | "raw-body": "2.5.2", 47 | "type-is": "~1.6.18", 48 | "unpipe": "1.0.0" 49 | }, 50 | "engines": { 51 | "node": ">= 0.8", 52 | "npm": "1.2.8000 || >= 1.4.16" 53 | } 54 | }, 55 | "node_modules/bytes": { 56 | "version": "3.1.2", 57 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 58 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 59 | "engines": { 60 | "node": ">= 0.8" 61 | } 62 | }, 63 | "node_modules/call-bind": { 64 | "version": "1.0.7", 65 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 66 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 67 | "dependencies": { 68 | "es-define-property": "^1.0.0", 69 | "es-errors": "^1.3.0", 70 | "function-bind": "^1.1.2", 71 | "get-intrinsic": "^1.2.4", 72 | "set-function-length": "^1.2.1" 73 | }, 74 | "engines": { 75 | "node": ">= 0.4" 76 | }, 77 | "funding": { 78 | "url": "https://github.com/sponsors/ljharb" 79 | } 80 | }, 81 | "node_modules/content-disposition": { 82 | "version": "0.5.4", 83 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 84 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 85 | "dependencies": { 86 | "safe-buffer": "5.2.1" 87 | }, 88 | "engines": { 89 | "node": ">= 0.6" 90 | } 91 | }, 92 | "node_modules/content-type": { 93 | "version": "1.0.5", 94 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 95 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 96 | "engines": { 97 | "node": ">= 0.6" 98 | } 99 | }, 100 | "node_modules/cookie": { 101 | "version": "0.6.0", 102 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", 103 | "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", 104 | "engines": { 105 | "node": ">= 0.6" 106 | } 107 | }, 108 | "node_modules/cookie-signature": { 109 | "version": "1.0.6", 110 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 111 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 112 | }, 113 | "node_modules/debug": { 114 | "version": "2.6.9", 115 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 116 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 117 | "dependencies": { 118 | "ms": "2.0.0" 119 | } 120 | }, 121 | "node_modules/define-data-property": { 122 | "version": "1.1.4", 123 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 124 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 125 | "dependencies": { 126 | "es-define-property": "^1.0.0", 127 | "es-errors": "^1.3.0", 128 | "gopd": "^1.0.1" 129 | }, 130 | "engines": { 131 | "node": ">= 0.4" 132 | }, 133 | "funding": { 134 | "url": "https://github.com/sponsors/ljharb" 135 | } 136 | }, 137 | "node_modules/depd": { 138 | "version": "2.0.0", 139 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 140 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 141 | "engines": { 142 | "node": ">= 0.8" 143 | } 144 | }, 145 | "node_modules/destroy": { 146 | "version": "1.2.0", 147 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 148 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 149 | "engines": { 150 | "node": ">= 0.8", 151 | "npm": "1.2.8000 || >= 1.4.16" 152 | } 153 | }, 154 | "node_modules/ee-first": { 155 | "version": "1.1.1", 156 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 157 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 158 | }, 159 | "node_modules/encodeurl": { 160 | "version": "2.0.0", 161 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 162 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 163 | "engines": { 164 | "node": ">= 0.8" 165 | } 166 | }, 167 | "node_modules/es-define-property": { 168 | "version": "1.0.0", 169 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 170 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 171 | "dependencies": { 172 | "get-intrinsic": "^1.2.4" 173 | }, 174 | "engines": { 175 | "node": ">= 0.4" 176 | } 177 | }, 178 | "node_modules/es-errors": { 179 | "version": "1.3.0", 180 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 181 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 182 | "engines": { 183 | "node": ">= 0.4" 184 | } 185 | }, 186 | "node_modules/escape-html": { 187 | "version": "1.0.3", 188 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 189 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 190 | }, 191 | "node_modules/etag": { 192 | "version": "1.8.1", 193 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 194 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 195 | "engines": { 196 | "node": ">= 0.6" 197 | } 198 | }, 199 | "node_modules/express": { 200 | "version": "4.21.0", 201 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", 202 | "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", 203 | "dependencies": { 204 | "accepts": "~1.3.8", 205 | "array-flatten": "1.1.1", 206 | "body-parser": "1.20.3", 207 | "content-disposition": "0.5.4", 208 | "content-type": "~1.0.4", 209 | "cookie": "0.6.0", 210 | "cookie-signature": "1.0.6", 211 | "debug": "2.6.9", 212 | "depd": "2.0.0", 213 | "encodeurl": "~2.0.0", 214 | "escape-html": "~1.0.3", 215 | "etag": "~1.8.1", 216 | "finalhandler": "1.3.1", 217 | "fresh": "0.5.2", 218 | "http-errors": "2.0.0", 219 | "merge-descriptors": "1.0.3", 220 | "methods": "~1.1.2", 221 | "on-finished": "2.4.1", 222 | "parseurl": "~1.3.3", 223 | "path-to-regexp": "0.1.10", 224 | "proxy-addr": "~2.0.7", 225 | "qs": "6.13.0", 226 | "range-parser": "~1.2.1", 227 | "safe-buffer": "5.2.1", 228 | "send": "0.19.0", 229 | "serve-static": "1.16.2", 230 | "setprototypeof": "1.2.0", 231 | "statuses": "2.0.1", 232 | "type-is": "~1.6.18", 233 | "utils-merge": "1.0.1", 234 | "vary": "~1.1.2" 235 | }, 236 | "engines": { 237 | "node": ">= 0.10.0" 238 | } 239 | }, 240 | "node_modules/finalhandler": { 241 | "version": "1.3.1", 242 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 243 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 244 | "dependencies": { 245 | "debug": "2.6.9", 246 | "encodeurl": "~2.0.0", 247 | "escape-html": "~1.0.3", 248 | "on-finished": "2.4.1", 249 | "parseurl": "~1.3.3", 250 | "statuses": "2.0.1", 251 | "unpipe": "~1.0.0" 252 | }, 253 | "engines": { 254 | "node": ">= 0.8" 255 | } 256 | }, 257 | "node_modules/forwarded": { 258 | "version": "0.2.0", 259 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 260 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 261 | "engines": { 262 | "node": ">= 0.6" 263 | } 264 | }, 265 | "node_modules/fresh": { 266 | "version": "0.5.2", 267 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 268 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 269 | "engines": { 270 | "node": ">= 0.6" 271 | } 272 | }, 273 | "node_modules/function-bind": { 274 | "version": "1.1.2", 275 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 276 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 277 | "funding": { 278 | "url": "https://github.com/sponsors/ljharb" 279 | } 280 | }, 281 | "node_modules/get-intrinsic": { 282 | "version": "1.2.4", 283 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 284 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 285 | "dependencies": { 286 | "es-errors": "^1.3.0", 287 | "function-bind": "^1.1.2", 288 | "has-proto": "^1.0.1", 289 | "has-symbols": "^1.0.3", 290 | "hasown": "^2.0.0" 291 | }, 292 | "engines": { 293 | "node": ">= 0.4" 294 | }, 295 | "funding": { 296 | "url": "https://github.com/sponsors/ljharb" 297 | } 298 | }, 299 | "node_modules/gopd": { 300 | "version": "1.0.1", 301 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 302 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 303 | "dependencies": { 304 | "get-intrinsic": "^1.1.3" 305 | }, 306 | "funding": { 307 | "url": "https://github.com/sponsors/ljharb" 308 | } 309 | }, 310 | "node_modules/has-property-descriptors": { 311 | "version": "1.0.2", 312 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 313 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 314 | "dependencies": { 315 | "es-define-property": "^1.0.0" 316 | }, 317 | "funding": { 318 | "url": "https://github.com/sponsors/ljharb" 319 | } 320 | }, 321 | "node_modules/has-proto": { 322 | "version": "1.0.3", 323 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 324 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 325 | "engines": { 326 | "node": ">= 0.4" 327 | }, 328 | "funding": { 329 | "url": "https://github.com/sponsors/ljharb" 330 | } 331 | }, 332 | "node_modules/has-symbols": { 333 | "version": "1.0.3", 334 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 335 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 336 | "engines": { 337 | "node": ">= 0.4" 338 | }, 339 | "funding": { 340 | "url": "https://github.com/sponsors/ljharb" 341 | } 342 | }, 343 | "node_modules/hasown": { 344 | "version": "2.0.2", 345 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 346 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 347 | "dependencies": { 348 | "function-bind": "^1.1.2" 349 | }, 350 | "engines": { 351 | "node": ">= 0.4" 352 | } 353 | }, 354 | "node_modules/http-errors": { 355 | "version": "2.0.0", 356 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 357 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 358 | "dependencies": { 359 | "depd": "2.0.0", 360 | "inherits": "2.0.4", 361 | "setprototypeof": "1.2.0", 362 | "statuses": "2.0.1", 363 | "toidentifier": "1.0.1" 364 | }, 365 | "engines": { 366 | "node": ">= 0.8" 367 | } 368 | }, 369 | "node_modules/iconv-lite": { 370 | "version": "0.4.24", 371 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 372 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 373 | "dependencies": { 374 | "safer-buffer": ">= 2.1.2 < 3" 375 | }, 376 | "engines": { 377 | "node": ">=0.10.0" 378 | } 379 | }, 380 | "node_modules/inherits": { 381 | "version": "2.0.4", 382 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 383 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 384 | }, 385 | "node_modules/ipaddr.js": { 386 | "version": "1.9.1", 387 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 388 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 389 | "engines": { 390 | "node": ">= 0.10" 391 | } 392 | }, 393 | "node_modules/media-typer": { 394 | "version": "0.3.0", 395 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 396 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 397 | "engines": { 398 | "node": ">= 0.6" 399 | } 400 | }, 401 | "node_modules/merge-descriptors": { 402 | "version": "1.0.3", 403 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 404 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 405 | "funding": { 406 | "url": "https://github.com/sponsors/sindresorhus" 407 | } 408 | }, 409 | "node_modules/methods": { 410 | "version": "1.1.2", 411 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 412 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 413 | "engines": { 414 | "node": ">= 0.6" 415 | } 416 | }, 417 | "node_modules/mime": { 418 | "version": "1.6.0", 419 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 420 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 421 | "bin": { 422 | "mime": "cli.js" 423 | }, 424 | "engines": { 425 | "node": ">=4" 426 | } 427 | }, 428 | "node_modules/mime-db": { 429 | "version": "1.52.0", 430 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 431 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 432 | "engines": { 433 | "node": ">= 0.6" 434 | } 435 | }, 436 | "node_modules/mime-types": { 437 | "version": "2.1.35", 438 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 439 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 440 | "dependencies": { 441 | "mime-db": "1.52.0" 442 | }, 443 | "engines": { 444 | "node": ">= 0.6" 445 | } 446 | }, 447 | "node_modules/ms": { 448 | "version": "2.0.0", 449 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 450 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 451 | }, 452 | "node_modules/negotiator": { 453 | "version": "0.6.3", 454 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 455 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 456 | "engines": { 457 | "node": ">= 0.6" 458 | } 459 | }, 460 | "node_modules/object-inspect": { 461 | "version": "1.13.2", 462 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 463 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", 464 | "engines": { 465 | "node": ">= 0.4" 466 | }, 467 | "funding": { 468 | "url": "https://github.com/sponsors/ljharb" 469 | } 470 | }, 471 | "node_modules/on-finished": { 472 | "version": "2.4.1", 473 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 474 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 475 | "dependencies": { 476 | "ee-first": "1.1.1" 477 | }, 478 | "engines": { 479 | "node": ">= 0.8" 480 | } 481 | }, 482 | "node_modules/parseurl": { 483 | "version": "1.3.3", 484 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 485 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 486 | "engines": { 487 | "node": ">= 0.8" 488 | } 489 | }, 490 | "node_modules/path-to-regexp": { 491 | "version": "0.1.10", 492 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", 493 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" 494 | }, 495 | "node_modules/proxy-addr": { 496 | "version": "2.0.7", 497 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 498 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 499 | "dependencies": { 500 | "forwarded": "0.2.0", 501 | "ipaddr.js": "1.9.1" 502 | }, 503 | "engines": { 504 | "node": ">= 0.10" 505 | } 506 | }, 507 | "node_modules/qs": { 508 | "version": "6.13.0", 509 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 510 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 511 | "dependencies": { 512 | "side-channel": "^1.0.6" 513 | }, 514 | "engines": { 515 | "node": ">=0.6" 516 | }, 517 | "funding": { 518 | "url": "https://github.com/sponsors/ljharb" 519 | } 520 | }, 521 | "node_modules/range-parser": { 522 | "version": "1.2.1", 523 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 524 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 525 | "engines": { 526 | "node": ">= 0.6" 527 | } 528 | }, 529 | "node_modules/raw-body": { 530 | "version": "2.5.2", 531 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 532 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 533 | "dependencies": { 534 | "bytes": "3.1.2", 535 | "http-errors": "2.0.0", 536 | "iconv-lite": "0.4.24", 537 | "unpipe": "1.0.0" 538 | }, 539 | "engines": { 540 | "node": ">= 0.8" 541 | } 542 | }, 543 | "node_modules/safe-buffer": { 544 | "version": "5.2.1", 545 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 546 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 547 | "funding": [ 548 | { 549 | "type": "github", 550 | "url": "https://github.com/sponsors/feross" 551 | }, 552 | { 553 | "type": "patreon", 554 | "url": "https://www.patreon.com/feross" 555 | }, 556 | { 557 | "type": "consulting", 558 | "url": "https://feross.org/support" 559 | } 560 | ] 561 | }, 562 | "node_modules/safer-buffer": { 563 | "version": "2.1.2", 564 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 565 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 566 | }, 567 | "node_modules/send": { 568 | "version": "0.19.0", 569 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 570 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 571 | "dependencies": { 572 | "debug": "2.6.9", 573 | "depd": "2.0.0", 574 | "destroy": "1.2.0", 575 | "encodeurl": "~1.0.2", 576 | "escape-html": "~1.0.3", 577 | "etag": "~1.8.1", 578 | "fresh": "0.5.2", 579 | "http-errors": "2.0.0", 580 | "mime": "1.6.0", 581 | "ms": "2.1.3", 582 | "on-finished": "2.4.1", 583 | "range-parser": "~1.2.1", 584 | "statuses": "2.0.1" 585 | }, 586 | "engines": { 587 | "node": ">= 0.8.0" 588 | } 589 | }, 590 | "node_modules/send/node_modules/encodeurl": { 591 | "version": "1.0.2", 592 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 593 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 594 | "engines": { 595 | "node": ">= 0.8" 596 | } 597 | }, 598 | "node_modules/send/node_modules/ms": { 599 | "version": "2.1.3", 600 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 601 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 602 | }, 603 | "node_modules/serve-static": { 604 | "version": "1.16.2", 605 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 606 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 607 | "dependencies": { 608 | "encodeurl": "~2.0.0", 609 | "escape-html": "~1.0.3", 610 | "parseurl": "~1.3.3", 611 | "send": "0.19.0" 612 | }, 613 | "engines": { 614 | "node": ">= 0.8.0" 615 | } 616 | }, 617 | "node_modules/set-function-length": { 618 | "version": "1.2.2", 619 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 620 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 621 | "dependencies": { 622 | "define-data-property": "^1.1.4", 623 | "es-errors": "^1.3.0", 624 | "function-bind": "^1.1.2", 625 | "get-intrinsic": "^1.2.4", 626 | "gopd": "^1.0.1", 627 | "has-property-descriptors": "^1.0.2" 628 | }, 629 | "engines": { 630 | "node": ">= 0.4" 631 | } 632 | }, 633 | "node_modules/setprototypeof": { 634 | "version": "1.2.0", 635 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 636 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 637 | }, 638 | "node_modules/side-channel": { 639 | "version": "1.0.6", 640 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 641 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 642 | "dependencies": { 643 | "call-bind": "^1.0.7", 644 | "es-errors": "^1.3.0", 645 | "get-intrinsic": "^1.2.4", 646 | "object-inspect": "^1.13.1" 647 | }, 648 | "engines": { 649 | "node": ">= 0.4" 650 | }, 651 | "funding": { 652 | "url": "https://github.com/sponsors/ljharb" 653 | } 654 | }, 655 | "node_modules/statuses": { 656 | "version": "2.0.1", 657 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 658 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 659 | "engines": { 660 | "node": ">= 0.8" 661 | } 662 | }, 663 | "node_modules/toidentifier": { 664 | "version": "1.0.1", 665 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 666 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 667 | "engines": { 668 | "node": ">=0.6" 669 | } 670 | }, 671 | "node_modules/type-is": { 672 | "version": "1.6.18", 673 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 674 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 675 | "dependencies": { 676 | "media-typer": "0.3.0", 677 | "mime-types": "~2.1.24" 678 | }, 679 | "engines": { 680 | "node": ">= 0.6" 681 | } 682 | }, 683 | "node_modules/unpipe": { 684 | "version": "1.0.0", 685 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 686 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 687 | "engines": { 688 | "node": ">= 0.8" 689 | } 690 | }, 691 | "node_modules/utils-merge": { 692 | "version": "1.0.1", 693 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 694 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 695 | "engines": { 696 | "node": ">= 0.4.0" 697 | } 698 | }, 699 | "node_modules/vary": { 700 | "version": "1.1.2", 701 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 702 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 703 | "engines": { 704 | "node": ">= 0.8" 705 | } 706 | } 707 | } 708 | } 709 | -------------------------------------------------------------------------------- /2. express-tutorial/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2.-express-tutorial", 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.21.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2. express-tutorial/routes-example.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | 4 | //root route 5 | app.get("/", (req, res) => { 6 | res.send("Welcome to our home page"); 7 | }); 8 | 9 | //get all products 10 | app.get("/products", (req, res) => { 11 | const products = [ 12 | { 13 | id: 1, 14 | label: "Product 1", 15 | }, 16 | { 17 | id: 2, 18 | label: "Product 2", 19 | }, 20 | { 21 | id: 3, 22 | label: "Product 3", 23 | }, 24 | ]; 25 | 26 | res.json(products); 27 | }); 28 | 29 | //get a single product 30 | app.get("/products/:productId", (req, res) => { 31 | console.log("req.params", req.params); 32 | 33 | const productId = parseInt(req.params.productId); 34 | const products = [ 35 | { 36 | id: 1, 37 | label: "Product 1", 38 | }, 39 | { 40 | id: 2, 41 | label: "Product 2", 42 | }, 43 | { 44 | id: 3, 45 | label: "Product 3", 46 | }, 47 | ]; 48 | 49 | const getSingleProduct = products.find((product) => product.id === productId); 50 | 51 | if (getSingleProduct) { 52 | res.json(getSingleProduct); 53 | } else { 54 | res.status(404).send("product is not found! please try with different id"); 55 | } 56 | }); 57 | 58 | const port = 3000; 59 | app.listen(port, () => { 60 | console.log(`Server is now running at port ${port}`); 61 | }); 62 | -------------------------------------------------------------------------------- /3. ejs-tutorial/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const path = require("path"); 3 | 4 | const app = express(); 5 | 6 | //set the view engine as ejs 7 | app.set("view engine", "ejs"); 8 | 9 | //set the directory for the views 10 | app.set("views", path.join(__dirname, "views")); 11 | 12 | const products = [ 13 | { 14 | id: 1, 15 | title: "Product 1", 16 | }, 17 | { 18 | id: 2, 19 | title: "Product 2", 20 | }, 21 | { 22 | id: 3, 23 | title: "Product 3", 24 | }, 25 | ]; 26 | 27 | app.get("/", (req, res) => { 28 | res.render("home", { title: "Home", products: products }); 29 | }); 30 | 31 | app.get("/about", (req, res) => { 32 | res.render("about", { title: "About page" }); 33 | }); 34 | 35 | const port = 3000; 36 | 37 | app.listen(port, () => { 38 | console.log("server is running"); 39 | }); 40 | -------------------------------------------------------------------------------- /3. ejs-tutorial/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3.-ejs-tutorial", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "3.-ejs-tutorial", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "ejs": "^3.1.10", 13 | "express": "^4.21.1" 14 | } 15 | }, 16 | "node_modules/accepts": { 17 | "version": "1.3.8", 18 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 19 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 20 | "dependencies": { 21 | "mime-types": "~2.1.34", 22 | "negotiator": "0.6.3" 23 | }, 24 | "engines": { 25 | "node": ">= 0.6" 26 | } 27 | }, 28 | "node_modules/ansi-styles": { 29 | "version": "4.3.0", 30 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 31 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 32 | "dependencies": { 33 | "color-convert": "^2.0.1" 34 | }, 35 | "engines": { 36 | "node": ">=8" 37 | }, 38 | "funding": { 39 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 40 | } 41 | }, 42 | "node_modules/array-flatten": { 43 | "version": "1.1.1", 44 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 45 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 46 | }, 47 | "node_modules/async": { 48 | "version": "3.2.6", 49 | "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", 50 | "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" 51 | }, 52 | "node_modules/balanced-match": { 53 | "version": "1.0.2", 54 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 55 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 56 | }, 57 | "node_modules/body-parser": { 58 | "version": "1.20.3", 59 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 60 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 61 | "dependencies": { 62 | "bytes": "3.1.2", 63 | "content-type": "~1.0.5", 64 | "debug": "2.6.9", 65 | "depd": "2.0.0", 66 | "destroy": "1.2.0", 67 | "http-errors": "2.0.0", 68 | "iconv-lite": "0.4.24", 69 | "on-finished": "2.4.1", 70 | "qs": "6.13.0", 71 | "raw-body": "2.5.2", 72 | "type-is": "~1.6.18", 73 | "unpipe": "1.0.0" 74 | }, 75 | "engines": { 76 | "node": ">= 0.8", 77 | "npm": "1.2.8000 || >= 1.4.16" 78 | } 79 | }, 80 | "node_modules/brace-expansion": { 81 | "version": "1.1.11", 82 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 83 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 84 | "dependencies": { 85 | "balanced-match": "^1.0.0", 86 | "concat-map": "0.0.1" 87 | } 88 | }, 89 | "node_modules/bytes": { 90 | "version": "3.1.2", 91 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 92 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 93 | "engines": { 94 | "node": ">= 0.8" 95 | } 96 | }, 97 | "node_modules/call-bind": { 98 | "version": "1.0.7", 99 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 100 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 101 | "dependencies": { 102 | "es-define-property": "^1.0.0", 103 | "es-errors": "^1.3.0", 104 | "function-bind": "^1.1.2", 105 | "get-intrinsic": "^1.2.4", 106 | "set-function-length": "^1.2.1" 107 | }, 108 | "engines": { 109 | "node": ">= 0.4" 110 | }, 111 | "funding": { 112 | "url": "https://github.com/sponsors/ljharb" 113 | } 114 | }, 115 | "node_modules/chalk": { 116 | "version": "4.1.2", 117 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 118 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 119 | "dependencies": { 120 | "ansi-styles": "^4.1.0", 121 | "supports-color": "^7.1.0" 122 | }, 123 | "engines": { 124 | "node": ">=10" 125 | }, 126 | "funding": { 127 | "url": "https://github.com/chalk/chalk?sponsor=1" 128 | } 129 | }, 130 | "node_modules/color-convert": { 131 | "version": "2.0.1", 132 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 133 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 134 | "dependencies": { 135 | "color-name": "~1.1.4" 136 | }, 137 | "engines": { 138 | "node": ">=7.0.0" 139 | } 140 | }, 141 | "node_modules/color-name": { 142 | "version": "1.1.4", 143 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 144 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 145 | }, 146 | "node_modules/concat-map": { 147 | "version": "0.0.1", 148 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 149 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 150 | }, 151 | "node_modules/content-disposition": { 152 | "version": "0.5.4", 153 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 154 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 155 | "dependencies": { 156 | "safe-buffer": "5.2.1" 157 | }, 158 | "engines": { 159 | "node": ">= 0.6" 160 | } 161 | }, 162 | "node_modules/content-type": { 163 | "version": "1.0.5", 164 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 165 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 166 | "engines": { 167 | "node": ">= 0.6" 168 | } 169 | }, 170 | "node_modules/cookie": { 171 | "version": "0.7.1", 172 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 173 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", 174 | "engines": { 175 | "node": ">= 0.6" 176 | } 177 | }, 178 | "node_modules/cookie-signature": { 179 | "version": "1.0.6", 180 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 181 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 182 | }, 183 | "node_modules/debug": { 184 | "version": "2.6.9", 185 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 186 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 187 | "dependencies": { 188 | "ms": "2.0.0" 189 | } 190 | }, 191 | "node_modules/define-data-property": { 192 | "version": "1.1.4", 193 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 194 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 195 | "dependencies": { 196 | "es-define-property": "^1.0.0", 197 | "es-errors": "^1.3.0", 198 | "gopd": "^1.0.1" 199 | }, 200 | "engines": { 201 | "node": ">= 0.4" 202 | }, 203 | "funding": { 204 | "url": "https://github.com/sponsors/ljharb" 205 | } 206 | }, 207 | "node_modules/depd": { 208 | "version": "2.0.0", 209 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 210 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 211 | "engines": { 212 | "node": ">= 0.8" 213 | } 214 | }, 215 | "node_modules/destroy": { 216 | "version": "1.2.0", 217 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 218 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 219 | "engines": { 220 | "node": ">= 0.8", 221 | "npm": "1.2.8000 || >= 1.4.16" 222 | } 223 | }, 224 | "node_modules/ee-first": { 225 | "version": "1.1.1", 226 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 227 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 228 | }, 229 | "node_modules/ejs": { 230 | "version": "3.1.10", 231 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", 232 | "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", 233 | "dependencies": { 234 | "jake": "^10.8.5" 235 | }, 236 | "bin": { 237 | "ejs": "bin/cli.js" 238 | }, 239 | "engines": { 240 | "node": ">=0.10.0" 241 | } 242 | }, 243 | "node_modules/encodeurl": { 244 | "version": "2.0.0", 245 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 246 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 247 | "engines": { 248 | "node": ">= 0.8" 249 | } 250 | }, 251 | "node_modules/es-define-property": { 252 | "version": "1.0.0", 253 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 254 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 255 | "dependencies": { 256 | "get-intrinsic": "^1.2.4" 257 | }, 258 | "engines": { 259 | "node": ">= 0.4" 260 | } 261 | }, 262 | "node_modules/es-errors": { 263 | "version": "1.3.0", 264 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 265 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 266 | "engines": { 267 | "node": ">= 0.4" 268 | } 269 | }, 270 | "node_modules/escape-html": { 271 | "version": "1.0.3", 272 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 273 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 274 | }, 275 | "node_modules/etag": { 276 | "version": "1.8.1", 277 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 278 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 279 | "engines": { 280 | "node": ">= 0.6" 281 | } 282 | }, 283 | "node_modules/express": { 284 | "version": "4.21.1", 285 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", 286 | "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", 287 | "dependencies": { 288 | "accepts": "~1.3.8", 289 | "array-flatten": "1.1.1", 290 | "body-parser": "1.20.3", 291 | "content-disposition": "0.5.4", 292 | "content-type": "~1.0.4", 293 | "cookie": "0.7.1", 294 | "cookie-signature": "1.0.6", 295 | "debug": "2.6.9", 296 | "depd": "2.0.0", 297 | "encodeurl": "~2.0.0", 298 | "escape-html": "~1.0.3", 299 | "etag": "~1.8.1", 300 | "finalhandler": "1.3.1", 301 | "fresh": "0.5.2", 302 | "http-errors": "2.0.0", 303 | "merge-descriptors": "1.0.3", 304 | "methods": "~1.1.2", 305 | "on-finished": "2.4.1", 306 | "parseurl": "~1.3.3", 307 | "path-to-regexp": "0.1.10", 308 | "proxy-addr": "~2.0.7", 309 | "qs": "6.13.0", 310 | "range-parser": "~1.2.1", 311 | "safe-buffer": "5.2.1", 312 | "send": "0.19.0", 313 | "serve-static": "1.16.2", 314 | "setprototypeof": "1.2.0", 315 | "statuses": "2.0.1", 316 | "type-is": "~1.6.18", 317 | "utils-merge": "1.0.1", 318 | "vary": "~1.1.2" 319 | }, 320 | "engines": { 321 | "node": ">= 0.10.0" 322 | } 323 | }, 324 | "node_modules/filelist": { 325 | "version": "1.0.4", 326 | "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", 327 | "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", 328 | "dependencies": { 329 | "minimatch": "^5.0.1" 330 | } 331 | }, 332 | "node_modules/filelist/node_modules/brace-expansion": { 333 | "version": "2.0.1", 334 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 335 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 336 | "dependencies": { 337 | "balanced-match": "^1.0.0" 338 | } 339 | }, 340 | "node_modules/filelist/node_modules/minimatch": { 341 | "version": "5.1.6", 342 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", 343 | "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", 344 | "dependencies": { 345 | "brace-expansion": "^2.0.1" 346 | }, 347 | "engines": { 348 | "node": ">=10" 349 | } 350 | }, 351 | "node_modules/finalhandler": { 352 | "version": "1.3.1", 353 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 354 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 355 | "dependencies": { 356 | "debug": "2.6.9", 357 | "encodeurl": "~2.0.0", 358 | "escape-html": "~1.0.3", 359 | "on-finished": "2.4.1", 360 | "parseurl": "~1.3.3", 361 | "statuses": "2.0.1", 362 | "unpipe": "~1.0.0" 363 | }, 364 | "engines": { 365 | "node": ">= 0.8" 366 | } 367 | }, 368 | "node_modules/forwarded": { 369 | "version": "0.2.0", 370 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 371 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 372 | "engines": { 373 | "node": ">= 0.6" 374 | } 375 | }, 376 | "node_modules/fresh": { 377 | "version": "0.5.2", 378 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 379 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 380 | "engines": { 381 | "node": ">= 0.6" 382 | } 383 | }, 384 | "node_modules/function-bind": { 385 | "version": "1.1.2", 386 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 387 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 388 | "funding": { 389 | "url": "https://github.com/sponsors/ljharb" 390 | } 391 | }, 392 | "node_modules/get-intrinsic": { 393 | "version": "1.2.4", 394 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 395 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 396 | "dependencies": { 397 | "es-errors": "^1.3.0", 398 | "function-bind": "^1.1.2", 399 | "has-proto": "^1.0.1", 400 | "has-symbols": "^1.0.3", 401 | "hasown": "^2.0.0" 402 | }, 403 | "engines": { 404 | "node": ">= 0.4" 405 | }, 406 | "funding": { 407 | "url": "https://github.com/sponsors/ljharb" 408 | } 409 | }, 410 | "node_modules/gopd": { 411 | "version": "1.0.1", 412 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 413 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 414 | "dependencies": { 415 | "get-intrinsic": "^1.1.3" 416 | }, 417 | "funding": { 418 | "url": "https://github.com/sponsors/ljharb" 419 | } 420 | }, 421 | "node_modules/has-flag": { 422 | "version": "4.0.0", 423 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 424 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 425 | "engines": { 426 | "node": ">=8" 427 | } 428 | }, 429 | "node_modules/has-property-descriptors": { 430 | "version": "1.0.2", 431 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 432 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 433 | "dependencies": { 434 | "es-define-property": "^1.0.0" 435 | }, 436 | "funding": { 437 | "url": "https://github.com/sponsors/ljharb" 438 | } 439 | }, 440 | "node_modules/has-proto": { 441 | "version": "1.0.3", 442 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 443 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 444 | "engines": { 445 | "node": ">= 0.4" 446 | }, 447 | "funding": { 448 | "url": "https://github.com/sponsors/ljharb" 449 | } 450 | }, 451 | "node_modules/has-symbols": { 452 | "version": "1.0.3", 453 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 454 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 455 | "engines": { 456 | "node": ">= 0.4" 457 | }, 458 | "funding": { 459 | "url": "https://github.com/sponsors/ljharb" 460 | } 461 | }, 462 | "node_modules/hasown": { 463 | "version": "2.0.2", 464 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 465 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 466 | "dependencies": { 467 | "function-bind": "^1.1.2" 468 | }, 469 | "engines": { 470 | "node": ">= 0.4" 471 | } 472 | }, 473 | "node_modules/http-errors": { 474 | "version": "2.0.0", 475 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 476 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 477 | "dependencies": { 478 | "depd": "2.0.0", 479 | "inherits": "2.0.4", 480 | "setprototypeof": "1.2.0", 481 | "statuses": "2.0.1", 482 | "toidentifier": "1.0.1" 483 | }, 484 | "engines": { 485 | "node": ">= 0.8" 486 | } 487 | }, 488 | "node_modules/iconv-lite": { 489 | "version": "0.4.24", 490 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 491 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 492 | "dependencies": { 493 | "safer-buffer": ">= 2.1.2 < 3" 494 | }, 495 | "engines": { 496 | "node": ">=0.10.0" 497 | } 498 | }, 499 | "node_modules/inherits": { 500 | "version": "2.0.4", 501 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 502 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 503 | }, 504 | "node_modules/ipaddr.js": { 505 | "version": "1.9.1", 506 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 507 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 508 | "engines": { 509 | "node": ">= 0.10" 510 | } 511 | }, 512 | "node_modules/jake": { 513 | "version": "10.9.2", 514 | "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", 515 | "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", 516 | "dependencies": { 517 | "async": "^3.2.3", 518 | "chalk": "^4.0.2", 519 | "filelist": "^1.0.4", 520 | "minimatch": "^3.1.2" 521 | }, 522 | "bin": { 523 | "jake": "bin/cli.js" 524 | }, 525 | "engines": { 526 | "node": ">=10" 527 | } 528 | }, 529 | "node_modules/media-typer": { 530 | "version": "0.3.0", 531 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 532 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 533 | "engines": { 534 | "node": ">= 0.6" 535 | } 536 | }, 537 | "node_modules/merge-descriptors": { 538 | "version": "1.0.3", 539 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 540 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 541 | "funding": { 542 | "url": "https://github.com/sponsors/sindresorhus" 543 | } 544 | }, 545 | "node_modules/methods": { 546 | "version": "1.1.2", 547 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 548 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 549 | "engines": { 550 | "node": ">= 0.6" 551 | } 552 | }, 553 | "node_modules/mime": { 554 | "version": "1.6.0", 555 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 556 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 557 | "bin": { 558 | "mime": "cli.js" 559 | }, 560 | "engines": { 561 | "node": ">=4" 562 | } 563 | }, 564 | "node_modules/mime-db": { 565 | "version": "1.52.0", 566 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 567 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 568 | "engines": { 569 | "node": ">= 0.6" 570 | } 571 | }, 572 | "node_modules/mime-types": { 573 | "version": "2.1.35", 574 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 575 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 576 | "dependencies": { 577 | "mime-db": "1.52.0" 578 | }, 579 | "engines": { 580 | "node": ">= 0.6" 581 | } 582 | }, 583 | "node_modules/minimatch": { 584 | "version": "3.1.2", 585 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 586 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 587 | "dependencies": { 588 | "brace-expansion": "^1.1.7" 589 | }, 590 | "engines": { 591 | "node": "*" 592 | } 593 | }, 594 | "node_modules/ms": { 595 | "version": "2.0.0", 596 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 597 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 598 | }, 599 | "node_modules/negotiator": { 600 | "version": "0.6.3", 601 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 602 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 603 | "engines": { 604 | "node": ">= 0.6" 605 | } 606 | }, 607 | "node_modules/object-inspect": { 608 | "version": "1.13.2", 609 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 610 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", 611 | "engines": { 612 | "node": ">= 0.4" 613 | }, 614 | "funding": { 615 | "url": "https://github.com/sponsors/ljharb" 616 | } 617 | }, 618 | "node_modules/on-finished": { 619 | "version": "2.4.1", 620 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 621 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 622 | "dependencies": { 623 | "ee-first": "1.1.1" 624 | }, 625 | "engines": { 626 | "node": ">= 0.8" 627 | } 628 | }, 629 | "node_modules/parseurl": { 630 | "version": "1.3.3", 631 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 632 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 633 | "engines": { 634 | "node": ">= 0.8" 635 | } 636 | }, 637 | "node_modules/path-to-regexp": { 638 | "version": "0.1.10", 639 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", 640 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" 641 | }, 642 | "node_modules/proxy-addr": { 643 | "version": "2.0.7", 644 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 645 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 646 | "dependencies": { 647 | "forwarded": "0.2.0", 648 | "ipaddr.js": "1.9.1" 649 | }, 650 | "engines": { 651 | "node": ">= 0.10" 652 | } 653 | }, 654 | "node_modules/qs": { 655 | "version": "6.13.0", 656 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 657 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 658 | "dependencies": { 659 | "side-channel": "^1.0.6" 660 | }, 661 | "engines": { 662 | "node": ">=0.6" 663 | }, 664 | "funding": { 665 | "url": "https://github.com/sponsors/ljharb" 666 | } 667 | }, 668 | "node_modules/range-parser": { 669 | "version": "1.2.1", 670 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 671 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 672 | "engines": { 673 | "node": ">= 0.6" 674 | } 675 | }, 676 | "node_modules/raw-body": { 677 | "version": "2.5.2", 678 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 679 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 680 | "dependencies": { 681 | "bytes": "3.1.2", 682 | "http-errors": "2.0.0", 683 | "iconv-lite": "0.4.24", 684 | "unpipe": "1.0.0" 685 | }, 686 | "engines": { 687 | "node": ">= 0.8" 688 | } 689 | }, 690 | "node_modules/safe-buffer": { 691 | "version": "5.2.1", 692 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 693 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 694 | "funding": [ 695 | { 696 | "type": "github", 697 | "url": "https://github.com/sponsors/feross" 698 | }, 699 | { 700 | "type": "patreon", 701 | "url": "https://www.patreon.com/feross" 702 | }, 703 | { 704 | "type": "consulting", 705 | "url": "https://feross.org/support" 706 | } 707 | ] 708 | }, 709 | "node_modules/safer-buffer": { 710 | "version": "2.1.2", 711 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 712 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 713 | }, 714 | "node_modules/send": { 715 | "version": "0.19.0", 716 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 717 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 718 | "dependencies": { 719 | "debug": "2.6.9", 720 | "depd": "2.0.0", 721 | "destroy": "1.2.0", 722 | "encodeurl": "~1.0.2", 723 | "escape-html": "~1.0.3", 724 | "etag": "~1.8.1", 725 | "fresh": "0.5.2", 726 | "http-errors": "2.0.0", 727 | "mime": "1.6.0", 728 | "ms": "2.1.3", 729 | "on-finished": "2.4.1", 730 | "range-parser": "~1.2.1", 731 | "statuses": "2.0.1" 732 | }, 733 | "engines": { 734 | "node": ">= 0.8.0" 735 | } 736 | }, 737 | "node_modules/send/node_modules/encodeurl": { 738 | "version": "1.0.2", 739 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 740 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 741 | "engines": { 742 | "node": ">= 0.8" 743 | } 744 | }, 745 | "node_modules/send/node_modules/ms": { 746 | "version": "2.1.3", 747 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 748 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 749 | }, 750 | "node_modules/serve-static": { 751 | "version": "1.16.2", 752 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 753 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 754 | "dependencies": { 755 | "encodeurl": "~2.0.0", 756 | "escape-html": "~1.0.3", 757 | "parseurl": "~1.3.3", 758 | "send": "0.19.0" 759 | }, 760 | "engines": { 761 | "node": ">= 0.8.0" 762 | } 763 | }, 764 | "node_modules/set-function-length": { 765 | "version": "1.2.2", 766 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 767 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 768 | "dependencies": { 769 | "define-data-property": "^1.1.4", 770 | "es-errors": "^1.3.0", 771 | "function-bind": "^1.1.2", 772 | "get-intrinsic": "^1.2.4", 773 | "gopd": "^1.0.1", 774 | "has-property-descriptors": "^1.0.2" 775 | }, 776 | "engines": { 777 | "node": ">= 0.4" 778 | } 779 | }, 780 | "node_modules/setprototypeof": { 781 | "version": "1.2.0", 782 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 783 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 784 | }, 785 | "node_modules/side-channel": { 786 | "version": "1.0.6", 787 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 788 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 789 | "dependencies": { 790 | "call-bind": "^1.0.7", 791 | "es-errors": "^1.3.0", 792 | "get-intrinsic": "^1.2.4", 793 | "object-inspect": "^1.13.1" 794 | }, 795 | "engines": { 796 | "node": ">= 0.4" 797 | }, 798 | "funding": { 799 | "url": "https://github.com/sponsors/ljharb" 800 | } 801 | }, 802 | "node_modules/statuses": { 803 | "version": "2.0.1", 804 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 805 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 806 | "engines": { 807 | "node": ">= 0.8" 808 | } 809 | }, 810 | "node_modules/supports-color": { 811 | "version": "7.2.0", 812 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 813 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 814 | "dependencies": { 815 | "has-flag": "^4.0.0" 816 | }, 817 | "engines": { 818 | "node": ">=8" 819 | } 820 | }, 821 | "node_modules/toidentifier": { 822 | "version": "1.0.1", 823 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 824 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 825 | "engines": { 826 | "node": ">=0.6" 827 | } 828 | }, 829 | "node_modules/type-is": { 830 | "version": "1.6.18", 831 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 832 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 833 | "dependencies": { 834 | "media-typer": "0.3.0", 835 | "mime-types": "~2.1.24" 836 | }, 837 | "engines": { 838 | "node": ">= 0.6" 839 | } 840 | }, 841 | "node_modules/unpipe": { 842 | "version": "1.0.0", 843 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 844 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 845 | "engines": { 846 | "node": ">= 0.8" 847 | } 848 | }, 849 | "node_modules/utils-merge": { 850 | "version": "1.0.1", 851 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 852 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 853 | "engines": { 854 | "node": ">= 0.4.0" 855 | } 856 | }, 857 | "node_modules/vary": { 858 | "version": "1.1.2", 859 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 860 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 861 | "engines": { 862 | "node": ">= 0.8" 863 | } 864 | } 865 | } 866 | } 867 | -------------------------------------------------------------------------------- /3. ejs-tutorial/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3.-ejs-tutorial", 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 | "ejs": "^3.1.10", 14 | "express": "^4.21.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /3. ejs-tutorial/views/about.ejs: -------------------------------------------------------------------------------- 1 | <%- include('components/header.ejs') %> 2 |

THis is our about page

3 | -------------------------------------------------------------------------------- /3. ejs-tutorial/views/components/header.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 |
10 |

EJS Template Header

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /3. ejs-tutorial/views/home.ejs: -------------------------------------------------------------------------------- 1 | <%- include('components/header.ejs') %> 2 |

Welcome to homepage

3 | 4 | 5 |
    6 | <% products.forEach(product=>{ %> 7 |
  • <%= product.title %>
  • 8 | <% }) %> 9 |
10 | -------------------------------------------------------------------------------- /4. rest-api-development/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | 4 | //Middleware 5 | app.use(express.json()); 6 | 7 | let books = [ 8 | { 9 | id: "1", 10 | title: "Book 1", 11 | }, 12 | { 13 | id: "2", 14 | title: "Book 2", 15 | }, 16 | ]; 17 | 18 | //intro route 19 | app.get("/", (req, res) => { 20 | res.json({ 21 | message: "Welcome to our bookstore api", 22 | }); 23 | }); 24 | 25 | //get all books 26 | app.get("/get", (req, res) => { 27 | res.json(books); 28 | }); 29 | 30 | //get a single book 31 | app.get("/get/:id", (req, res) => { 32 | const book = books.find((item) => item.id === req.params.id); 33 | if (book) { 34 | res.status(200).json(book); 35 | } else { 36 | res.status(404).json({ 37 | message: "Book not found! Please try with a different Book ID", 38 | }); 39 | } 40 | }); 41 | 42 | //add a new book 43 | app.post("/add", (req, res) => { 44 | const newBook = { 45 | id: Math.floor(Math.random() * 1000).toString(), 46 | title: `Book ${Math.floor(Math.random() * 1000)}`, 47 | }; 48 | 49 | books.push(newBook); 50 | res.status(200).json({ 51 | data: newBook, 52 | message: "New book is added successfully", 53 | }); 54 | }); 55 | 56 | //update a book 57 | app.put("/update/:id", (req, res) => { 58 | const findCurrentBook = books.find( 59 | (bookItem) => bookItem.id === req.params.id 60 | ); 61 | if (findCurrentBook) { 62 | findCurrentBook.title = req.body.title || findCurrentBook.title; 63 | 64 | res.status(200).json({ 65 | message: `Book with ID ${req.params.id} updated successfully`, 66 | data: findCurrentBook, 67 | }); 68 | } else { 69 | res.status(404).json({ 70 | message: "Book not found", 71 | }); 72 | } 73 | }); 74 | 75 | app.delete("/delete/:id", (req, res) => { 76 | const findIndexOfCurrentBook = books.findIndex( 77 | (item) => item.id === req.params.id 78 | ); 79 | if (findIndexOfCurrentBook !== -1) { 80 | const deletedBook = books.splice(findIndexOfCurrentBook, 1); 81 | res.status(200).json({ 82 | message: "Book deleted successfully", 83 | data: deletedBook[0], 84 | }); 85 | } else { 86 | res.status(404).json({ 87 | message: "Book not found", 88 | }); 89 | } 90 | }); 91 | 92 | const PORT = 3000; 93 | app.listen(PORT, () => { 94 | console.log(`Server is now running on port ${PORT}`); 95 | }); 96 | -------------------------------------------------------------------------------- /4. rest-api-development/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "4.-rest-api-development", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "4.-rest-api-development", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.21.1" 13 | } 14 | }, 15 | "node_modules/accepts": { 16 | "version": "1.3.8", 17 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 18 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 19 | "dependencies": { 20 | "mime-types": "~2.1.34", 21 | "negotiator": "0.6.3" 22 | }, 23 | "engines": { 24 | "node": ">= 0.6" 25 | } 26 | }, 27 | "node_modules/array-flatten": { 28 | "version": "1.1.1", 29 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 30 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 31 | }, 32 | "node_modules/body-parser": { 33 | "version": "1.20.3", 34 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 35 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 36 | "dependencies": { 37 | "bytes": "3.1.2", 38 | "content-type": "~1.0.5", 39 | "debug": "2.6.9", 40 | "depd": "2.0.0", 41 | "destroy": "1.2.0", 42 | "http-errors": "2.0.0", 43 | "iconv-lite": "0.4.24", 44 | "on-finished": "2.4.1", 45 | "qs": "6.13.0", 46 | "raw-body": "2.5.2", 47 | "type-is": "~1.6.18", 48 | "unpipe": "1.0.0" 49 | }, 50 | "engines": { 51 | "node": ">= 0.8", 52 | "npm": "1.2.8000 || >= 1.4.16" 53 | } 54 | }, 55 | "node_modules/bytes": { 56 | "version": "3.1.2", 57 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 58 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 59 | "engines": { 60 | "node": ">= 0.8" 61 | } 62 | }, 63 | "node_modules/call-bind": { 64 | "version": "1.0.7", 65 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 66 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 67 | "dependencies": { 68 | "es-define-property": "^1.0.0", 69 | "es-errors": "^1.3.0", 70 | "function-bind": "^1.1.2", 71 | "get-intrinsic": "^1.2.4", 72 | "set-function-length": "^1.2.1" 73 | }, 74 | "engines": { 75 | "node": ">= 0.4" 76 | }, 77 | "funding": { 78 | "url": "https://github.com/sponsors/ljharb" 79 | } 80 | }, 81 | "node_modules/content-disposition": { 82 | "version": "0.5.4", 83 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 84 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 85 | "dependencies": { 86 | "safe-buffer": "5.2.1" 87 | }, 88 | "engines": { 89 | "node": ">= 0.6" 90 | } 91 | }, 92 | "node_modules/content-type": { 93 | "version": "1.0.5", 94 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 95 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 96 | "engines": { 97 | "node": ">= 0.6" 98 | } 99 | }, 100 | "node_modules/cookie": { 101 | "version": "0.7.1", 102 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 103 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", 104 | "engines": { 105 | "node": ">= 0.6" 106 | } 107 | }, 108 | "node_modules/cookie-signature": { 109 | "version": "1.0.6", 110 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 111 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 112 | }, 113 | "node_modules/debug": { 114 | "version": "2.6.9", 115 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 116 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 117 | "dependencies": { 118 | "ms": "2.0.0" 119 | } 120 | }, 121 | "node_modules/define-data-property": { 122 | "version": "1.1.4", 123 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 124 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 125 | "dependencies": { 126 | "es-define-property": "^1.0.0", 127 | "es-errors": "^1.3.0", 128 | "gopd": "^1.0.1" 129 | }, 130 | "engines": { 131 | "node": ">= 0.4" 132 | }, 133 | "funding": { 134 | "url": "https://github.com/sponsors/ljharb" 135 | } 136 | }, 137 | "node_modules/depd": { 138 | "version": "2.0.0", 139 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 140 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 141 | "engines": { 142 | "node": ">= 0.8" 143 | } 144 | }, 145 | "node_modules/destroy": { 146 | "version": "1.2.0", 147 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 148 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 149 | "engines": { 150 | "node": ">= 0.8", 151 | "npm": "1.2.8000 || >= 1.4.16" 152 | } 153 | }, 154 | "node_modules/ee-first": { 155 | "version": "1.1.1", 156 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 157 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 158 | }, 159 | "node_modules/encodeurl": { 160 | "version": "2.0.0", 161 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 162 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 163 | "engines": { 164 | "node": ">= 0.8" 165 | } 166 | }, 167 | "node_modules/es-define-property": { 168 | "version": "1.0.0", 169 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 170 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 171 | "dependencies": { 172 | "get-intrinsic": "^1.2.4" 173 | }, 174 | "engines": { 175 | "node": ">= 0.4" 176 | } 177 | }, 178 | "node_modules/es-errors": { 179 | "version": "1.3.0", 180 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 181 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 182 | "engines": { 183 | "node": ">= 0.4" 184 | } 185 | }, 186 | "node_modules/escape-html": { 187 | "version": "1.0.3", 188 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 189 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 190 | }, 191 | "node_modules/etag": { 192 | "version": "1.8.1", 193 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 194 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 195 | "engines": { 196 | "node": ">= 0.6" 197 | } 198 | }, 199 | "node_modules/express": { 200 | "version": "4.21.1", 201 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", 202 | "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", 203 | "dependencies": { 204 | "accepts": "~1.3.8", 205 | "array-flatten": "1.1.1", 206 | "body-parser": "1.20.3", 207 | "content-disposition": "0.5.4", 208 | "content-type": "~1.0.4", 209 | "cookie": "0.7.1", 210 | "cookie-signature": "1.0.6", 211 | "debug": "2.6.9", 212 | "depd": "2.0.0", 213 | "encodeurl": "~2.0.0", 214 | "escape-html": "~1.0.3", 215 | "etag": "~1.8.1", 216 | "finalhandler": "1.3.1", 217 | "fresh": "0.5.2", 218 | "http-errors": "2.0.0", 219 | "merge-descriptors": "1.0.3", 220 | "methods": "~1.1.2", 221 | "on-finished": "2.4.1", 222 | "parseurl": "~1.3.3", 223 | "path-to-regexp": "0.1.10", 224 | "proxy-addr": "~2.0.7", 225 | "qs": "6.13.0", 226 | "range-parser": "~1.2.1", 227 | "safe-buffer": "5.2.1", 228 | "send": "0.19.0", 229 | "serve-static": "1.16.2", 230 | "setprototypeof": "1.2.0", 231 | "statuses": "2.0.1", 232 | "type-is": "~1.6.18", 233 | "utils-merge": "1.0.1", 234 | "vary": "~1.1.2" 235 | }, 236 | "engines": { 237 | "node": ">= 0.10.0" 238 | } 239 | }, 240 | "node_modules/finalhandler": { 241 | "version": "1.3.1", 242 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 243 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 244 | "dependencies": { 245 | "debug": "2.6.9", 246 | "encodeurl": "~2.0.0", 247 | "escape-html": "~1.0.3", 248 | "on-finished": "2.4.1", 249 | "parseurl": "~1.3.3", 250 | "statuses": "2.0.1", 251 | "unpipe": "~1.0.0" 252 | }, 253 | "engines": { 254 | "node": ">= 0.8" 255 | } 256 | }, 257 | "node_modules/forwarded": { 258 | "version": "0.2.0", 259 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 260 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 261 | "engines": { 262 | "node": ">= 0.6" 263 | } 264 | }, 265 | "node_modules/fresh": { 266 | "version": "0.5.2", 267 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 268 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 269 | "engines": { 270 | "node": ">= 0.6" 271 | } 272 | }, 273 | "node_modules/function-bind": { 274 | "version": "1.1.2", 275 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 276 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 277 | "funding": { 278 | "url": "https://github.com/sponsors/ljharb" 279 | } 280 | }, 281 | "node_modules/get-intrinsic": { 282 | "version": "1.2.4", 283 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 284 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 285 | "dependencies": { 286 | "es-errors": "^1.3.0", 287 | "function-bind": "^1.1.2", 288 | "has-proto": "^1.0.1", 289 | "has-symbols": "^1.0.3", 290 | "hasown": "^2.0.0" 291 | }, 292 | "engines": { 293 | "node": ">= 0.4" 294 | }, 295 | "funding": { 296 | "url": "https://github.com/sponsors/ljharb" 297 | } 298 | }, 299 | "node_modules/gopd": { 300 | "version": "1.0.1", 301 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 302 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 303 | "dependencies": { 304 | "get-intrinsic": "^1.1.3" 305 | }, 306 | "funding": { 307 | "url": "https://github.com/sponsors/ljharb" 308 | } 309 | }, 310 | "node_modules/has-property-descriptors": { 311 | "version": "1.0.2", 312 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 313 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 314 | "dependencies": { 315 | "es-define-property": "^1.0.0" 316 | }, 317 | "funding": { 318 | "url": "https://github.com/sponsors/ljharb" 319 | } 320 | }, 321 | "node_modules/has-proto": { 322 | "version": "1.0.3", 323 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 324 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 325 | "engines": { 326 | "node": ">= 0.4" 327 | }, 328 | "funding": { 329 | "url": "https://github.com/sponsors/ljharb" 330 | } 331 | }, 332 | "node_modules/has-symbols": { 333 | "version": "1.0.3", 334 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 335 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 336 | "engines": { 337 | "node": ">= 0.4" 338 | }, 339 | "funding": { 340 | "url": "https://github.com/sponsors/ljharb" 341 | } 342 | }, 343 | "node_modules/hasown": { 344 | "version": "2.0.2", 345 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 346 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 347 | "dependencies": { 348 | "function-bind": "^1.1.2" 349 | }, 350 | "engines": { 351 | "node": ">= 0.4" 352 | } 353 | }, 354 | "node_modules/http-errors": { 355 | "version": "2.0.0", 356 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 357 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 358 | "dependencies": { 359 | "depd": "2.0.0", 360 | "inherits": "2.0.4", 361 | "setprototypeof": "1.2.0", 362 | "statuses": "2.0.1", 363 | "toidentifier": "1.0.1" 364 | }, 365 | "engines": { 366 | "node": ">= 0.8" 367 | } 368 | }, 369 | "node_modules/iconv-lite": { 370 | "version": "0.4.24", 371 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 372 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 373 | "dependencies": { 374 | "safer-buffer": ">= 2.1.2 < 3" 375 | }, 376 | "engines": { 377 | "node": ">=0.10.0" 378 | } 379 | }, 380 | "node_modules/inherits": { 381 | "version": "2.0.4", 382 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 383 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 384 | }, 385 | "node_modules/ipaddr.js": { 386 | "version": "1.9.1", 387 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 388 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 389 | "engines": { 390 | "node": ">= 0.10" 391 | } 392 | }, 393 | "node_modules/media-typer": { 394 | "version": "0.3.0", 395 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 396 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 397 | "engines": { 398 | "node": ">= 0.6" 399 | } 400 | }, 401 | "node_modules/merge-descriptors": { 402 | "version": "1.0.3", 403 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 404 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 405 | "funding": { 406 | "url": "https://github.com/sponsors/sindresorhus" 407 | } 408 | }, 409 | "node_modules/methods": { 410 | "version": "1.1.2", 411 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 412 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 413 | "engines": { 414 | "node": ">= 0.6" 415 | } 416 | }, 417 | "node_modules/mime": { 418 | "version": "1.6.0", 419 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 420 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 421 | "bin": { 422 | "mime": "cli.js" 423 | }, 424 | "engines": { 425 | "node": ">=4" 426 | } 427 | }, 428 | "node_modules/mime-db": { 429 | "version": "1.52.0", 430 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 431 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 432 | "engines": { 433 | "node": ">= 0.6" 434 | } 435 | }, 436 | "node_modules/mime-types": { 437 | "version": "2.1.35", 438 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 439 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 440 | "dependencies": { 441 | "mime-db": "1.52.0" 442 | }, 443 | "engines": { 444 | "node": ">= 0.6" 445 | } 446 | }, 447 | "node_modules/ms": { 448 | "version": "2.0.0", 449 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 450 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 451 | }, 452 | "node_modules/negotiator": { 453 | "version": "0.6.3", 454 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 455 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 456 | "engines": { 457 | "node": ">= 0.6" 458 | } 459 | }, 460 | "node_modules/object-inspect": { 461 | "version": "1.13.2", 462 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 463 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", 464 | "engines": { 465 | "node": ">= 0.4" 466 | }, 467 | "funding": { 468 | "url": "https://github.com/sponsors/ljharb" 469 | } 470 | }, 471 | "node_modules/on-finished": { 472 | "version": "2.4.1", 473 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 474 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 475 | "dependencies": { 476 | "ee-first": "1.1.1" 477 | }, 478 | "engines": { 479 | "node": ">= 0.8" 480 | } 481 | }, 482 | "node_modules/parseurl": { 483 | "version": "1.3.3", 484 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 485 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 486 | "engines": { 487 | "node": ">= 0.8" 488 | } 489 | }, 490 | "node_modules/path-to-regexp": { 491 | "version": "0.1.10", 492 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", 493 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" 494 | }, 495 | "node_modules/proxy-addr": { 496 | "version": "2.0.7", 497 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 498 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 499 | "dependencies": { 500 | "forwarded": "0.2.0", 501 | "ipaddr.js": "1.9.1" 502 | }, 503 | "engines": { 504 | "node": ">= 0.10" 505 | } 506 | }, 507 | "node_modules/qs": { 508 | "version": "6.13.0", 509 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 510 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 511 | "dependencies": { 512 | "side-channel": "^1.0.6" 513 | }, 514 | "engines": { 515 | "node": ">=0.6" 516 | }, 517 | "funding": { 518 | "url": "https://github.com/sponsors/ljharb" 519 | } 520 | }, 521 | "node_modules/range-parser": { 522 | "version": "1.2.1", 523 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 524 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 525 | "engines": { 526 | "node": ">= 0.6" 527 | } 528 | }, 529 | "node_modules/raw-body": { 530 | "version": "2.5.2", 531 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 532 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 533 | "dependencies": { 534 | "bytes": "3.1.2", 535 | "http-errors": "2.0.0", 536 | "iconv-lite": "0.4.24", 537 | "unpipe": "1.0.0" 538 | }, 539 | "engines": { 540 | "node": ">= 0.8" 541 | } 542 | }, 543 | "node_modules/safe-buffer": { 544 | "version": "5.2.1", 545 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 546 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 547 | "funding": [ 548 | { 549 | "type": "github", 550 | "url": "https://github.com/sponsors/feross" 551 | }, 552 | { 553 | "type": "patreon", 554 | "url": "https://www.patreon.com/feross" 555 | }, 556 | { 557 | "type": "consulting", 558 | "url": "https://feross.org/support" 559 | } 560 | ] 561 | }, 562 | "node_modules/safer-buffer": { 563 | "version": "2.1.2", 564 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 565 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 566 | }, 567 | "node_modules/send": { 568 | "version": "0.19.0", 569 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 570 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 571 | "dependencies": { 572 | "debug": "2.6.9", 573 | "depd": "2.0.0", 574 | "destroy": "1.2.0", 575 | "encodeurl": "~1.0.2", 576 | "escape-html": "~1.0.3", 577 | "etag": "~1.8.1", 578 | "fresh": "0.5.2", 579 | "http-errors": "2.0.0", 580 | "mime": "1.6.0", 581 | "ms": "2.1.3", 582 | "on-finished": "2.4.1", 583 | "range-parser": "~1.2.1", 584 | "statuses": "2.0.1" 585 | }, 586 | "engines": { 587 | "node": ">= 0.8.0" 588 | } 589 | }, 590 | "node_modules/send/node_modules/encodeurl": { 591 | "version": "1.0.2", 592 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 593 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 594 | "engines": { 595 | "node": ">= 0.8" 596 | } 597 | }, 598 | "node_modules/send/node_modules/ms": { 599 | "version": "2.1.3", 600 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 601 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 602 | }, 603 | "node_modules/serve-static": { 604 | "version": "1.16.2", 605 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 606 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 607 | "dependencies": { 608 | "encodeurl": "~2.0.0", 609 | "escape-html": "~1.0.3", 610 | "parseurl": "~1.3.3", 611 | "send": "0.19.0" 612 | }, 613 | "engines": { 614 | "node": ">= 0.8.0" 615 | } 616 | }, 617 | "node_modules/set-function-length": { 618 | "version": "1.2.2", 619 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 620 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 621 | "dependencies": { 622 | "define-data-property": "^1.1.4", 623 | "es-errors": "^1.3.0", 624 | "function-bind": "^1.1.2", 625 | "get-intrinsic": "^1.2.4", 626 | "gopd": "^1.0.1", 627 | "has-property-descriptors": "^1.0.2" 628 | }, 629 | "engines": { 630 | "node": ">= 0.4" 631 | } 632 | }, 633 | "node_modules/setprototypeof": { 634 | "version": "1.2.0", 635 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 636 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 637 | }, 638 | "node_modules/side-channel": { 639 | "version": "1.0.6", 640 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 641 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 642 | "dependencies": { 643 | "call-bind": "^1.0.7", 644 | "es-errors": "^1.3.0", 645 | "get-intrinsic": "^1.2.4", 646 | "object-inspect": "^1.13.1" 647 | }, 648 | "engines": { 649 | "node": ">= 0.4" 650 | }, 651 | "funding": { 652 | "url": "https://github.com/sponsors/ljharb" 653 | } 654 | }, 655 | "node_modules/statuses": { 656 | "version": "2.0.1", 657 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 658 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 659 | "engines": { 660 | "node": ">= 0.8" 661 | } 662 | }, 663 | "node_modules/toidentifier": { 664 | "version": "1.0.1", 665 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 666 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 667 | "engines": { 668 | "node": ">=0.6" 669 | } 670 | }, 671 | "node_modules/type-is": { 672 | "version": "1.6.18", 673 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 674 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 675 | "dependencies": { 676 | "media-typer": "0.3.0", 677 | "mime-types": "~2.1.24" 678 | }, 679 | "engines": { 680 | "node": ">= 0.6" 681 | } 682 | }, 683 | "node_modules/unpipe": { 684 | "version": "1.0.0", 685 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 686 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 687 | "engines": { 688 | "node": ">= 0.8" 689 | } 690 | }, 691 | "node_modules/utils-merge": { 692 | "version": "1.0.1", 693 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 694 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 695 | "engines": { 696 | "node": ">= 0.4.0" 697 | } 698 | }, 699 | "node_modules/vary": { 700 | "version": "1.1.2", 701 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 702 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 703 | "engines": { 704 | "node": ">= 0.8" 705 | } 706 | } 707 | } 708 | } 709 | -------------------------------------------------------------------------------- /4. rest-api-development/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "4.-rest-api-development", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.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.21.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /5. mongodb-basics/app.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | mongoose 4 | .connect( 5 | "mongodb+srv://sangammukherjee2022:sangammukherjee2024@cluster0.7qjl1.mongodb.net/" 6 | ) 7 | .then(() => console.log("database connected successfully")) 8 | .catch((e) => console.log(e)); 9 | 10 | const userSchema = new mongoose.Schema({ 11 | name: String, 12 | email: String, 13 | age: Number, 14 | isActive: Boolean, 15 | tags: [String], 16 | createdAt: { type: Date, default: Date.now }, 17 | }); 18 | 19 | //create user model 20 | const User = mongoose.model("User", userSchema); 21 | 22 | async function runQueryExamples() { 23 | try { 24 | //create a new document 25 | const newUser = await User.create({ 26 | name: "Updated User", 27 | email: "updated@gmail.com", 28 | age: "75", 29 | isActive: true, 30 | tags: ["developer"], 31 | }); 32 | // const newUser = new User({ 33 | // name: "Raj Mukherjee", 34 | // email: "raj@gmail.com", 35 | // age: "40", 36 | // isActive: true, 37 | // tags: ["developer", "designer", "manager"], 38 | // }); 39 | // await newUser.save(); 40 | console.log("Created new user", newUser); 41 | // const allUsers = await User.find({}); 42 | // console.log(allUsers); 43 | // const getUserOfActiveFalse = await User.find({ isActive: true }); 44 | // console.log(getUserOfActiveFalse); 45 | // const getJohnDoeUser = await User.findOne({ name: "John Doe" }); 46 | // console.log(getJohnDoeUser); 47 | // const getLastCreatedUserByUserId = await User.findById(newUser._id); 48 | // console.log(getLastCreatedUserByUserId, "getLastCreatedUserByUserId"); 49 | // const selectedFields = await User.find().select("name email -_id"); 50 | // console.log(selectedFields); 51 | // const limitedUsers = await User.find().limit(5).skip(1); 52 | // console.log(limitedUsers); 53 | // const sortedUsers = await User.find().sort({ age: 1 }); 54 | // console.log(sortedUsers); 55 | 56 | // const countDocuments = await User.countDocuments({ isActive: true }); 57 | // console.log(countDocuments); 58 | 59 | // const deletedUser = await User.findByIdAndDelete(newUser._id); 60 | // console.log("deleted user ->", deletedUser); 61 | 62 | const updateUser = await User.findByIdAndUpdate( 63 | newUser._id, 64 | { 65 | $set: { age: 100 }, 66 | $push: { tags: "updated" }, 67 | }, 68 | { new: true } 69 | ); 70 | console.log("updated user", updateUser); 71 | } catch (e) { 72 | console.log("Error ->", e); 73 | } finally { 74 | await mongoose.connection.close(); 75 | } 76 | } 77 | 78 | runQueryExamples(); 79 | -------------------------------------------------------------------------------- /5. mongodb-basics/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "5.-mongodb-basics", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "5.-mongodb-basics", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mongoose": "^8.7.1" 13 | } 14 | }, 15 | "node_modules/@mongodb-js/saslprep": { 16 | "version": "1.1.9", 17 | "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", 18 | "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", 19 | "dependencies": { 20 | "sparse-bitfield": "^3.0.3" 21 | } 22 | }, 23 | "node_modules/@types/webidl-conversions": { 24 | "version": "7.0.3", 25 | "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", 26 | "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" 27 | }, 28 | "node_modules/@types/whatwg-url": { 29 | "version": "11.0.5", 30 | "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", 31 | "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", 32 | "dependencies": { 33 | "@types/webidl-conversions": "*" 34 | } 35 | }, 36 | "node_modules/bson": { 37 | "version": "6.8.0", 38 | "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", 39 | "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==", 40 | "engines": { 41 | "node": ">=16.20.1" 42 | } 43 | }, 44 | "node_modules/debug": { 45 | "version": "4.3.7", 46 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 47 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 48 | "dependencies": { 49 | "ms": "^2.1.3" 50 | }, 51 | "engines": { 52 | "node": ">=6.0" 53 | }, 54 | "peerDependenciesMeta": { 55 | "supports-color": { 56 | "optional": true 57 | } 58 | } 59 | }, 60 | "node_modules/kareem": { 61 | "version": "2.6.3", 62 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", 63 | "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", 64 | "engines": { 65 | "node": ">=12.0.0" 66 | } 67 | }, 68 | "node_modules/memory-pager": { 69 | "version": "1.5.0", 70 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 71 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" 72 | }, 73 | "node_modules/mongodb": { 74 | "version": "6.9.0", 75 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.9.0.tgz", 76 | "integrity": "sha512-UMopBVx1LmEUbW/QE0Hw18u583PEDVQmUmVzzBRH0o/xtE9DBRA5ZYLOjpLIa03i8FXjzvQECJcqoMvCXftTUA==", 77 | "dependencies": { 78 | "@mongodb-js/saslprep": "^1.1.5", 79 | "bson": "^6.7.0", 80 | "mongodb-connection-string-url": "^3.0.0" 81 | }, 82 | "engines": { 83 | "node": ">=16.20.1" 84 | }, 85 | "peerDependencies": { 86 | "@aws-sdk/credential-providers": "^3.188.0", 87 | "@mongodb-js/zstd": "^1.1.0", 88 | "gcp-metadata": "^5.2.0", 89 | "kerberos": "^2.0.1", 90 | "mongodb-client-encryption": ">=6.0.0 <7", 91 | "snappy": "^7.2.2", 92 | "socks": "^2.7.1" 93 | }, 94 | "peerDependenciesMeta": { 95 | "@aws-sdk/credential-providers": { 96 | "optional": true 97 | }, 98 | "@mongodb-js/zstd": { 99 | "optional": true 100 | }, 101 | "gcp-metadata": { 102 | "optional": true 103 | }, 104 | "kerberos": { 105 | "optional": true 106 | }, 107 | "mongodb-client-encryption": { 108 | "optional": true 109 | }, 110 | "snappy": { 111 | "optional": true 112 | }, 113 | "socks": { 114 | "optional": true 115 | } 116 | } 117 | }, 118 | "node_modules/mongodb-connection-string-url": { 119 | "version": "3.0.1", 120 | "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", 121 | "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", 122 | "dependencies": { 123 | "@types/whatwg-url": "^11.0.2", 124 | "whatwg-url": "^13.0.0" 125 | } 126 | }, 127 | "node_modules/mongoose": { 128 | "version": "8.7.1", 129 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.1.tgz", 130 | "integrity": "sha512-RpNMyhyzLVCVbf8xTVbrf/18G3MqQzNw5pJdvOJ60fzbCa3cOZzz9L+8XpqzBXtRlgZGWv0T7MmOtvrT8ocp1Q==", 131 | "dependencies": { 132 | "bson": "^6.7.0", 133 | "kareem": "2.6.3", 134 | "mongodb": "6.9.0", 135 | "mpath": "0.9.0", 136 | "mquery": "5.0.0", 137 | "ms": "2.1.3", 138 | "sift": "17.1.3" 139 | }, 140 | "engines": { 141 | "node": ">=16.20.1" 142 | }, 143 | "funding": { 144 | "type": "opencollective", 145 | "url": "https://opencollective.com/mongoose" 146 | } 147 | }, 148 | "node_modules/mpath": { 149 | "version": "0.9.0", 150 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", 151 | "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", 152 | "engines": { 153 | "node": ">=4.0.0" 154 | } 155 | }, 156 | "node_modules/mquery": { 157 | "version": "5.0.0", 158 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", 159 | "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", 160 | "dependencies": { 161 | "debug": "4.x" 162 | }, 163 | "engines": { 164 | "node": ">=14.0.0" 165 | } 166 | }, 167 | "node_modules/ms": { 168 | "version": "2.1.3", 169 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 170 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 171 | }, 172 | "node_modules/punycode": { 173 | "version": "2.3.1", 174 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 175 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 176 | "engines": { 177 | "node": ">=6" 178 | } 179 | }, 180 | "node_modules/sift": { 181 | "version": "17.1.3", 182 | "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", 183 | "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" 184 | }, 185 | "node_modules/sparse-bitfield": { 186 | "version": "3.0.3", 187 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 188 | "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", 189 | "dependencies": { 190 | "memory-pager": "^1.0.2" 191 | } 192 | }, 193 | "node_modules/tr46": { 194 | "version": "4.1.1", 195 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", 196 | "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", 197 | "dependencies": { 198 | "punycode": "^2.3.0" 199 | }, 200 | "engines": { 201 | "node": ">=14" 202 | } 203 | }, 204 | "node_modules/webidl-conversions": { 205 | "version": "7.0.0", 206 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 207 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", 208 | "engines": { 209 | "node": ">=12" 210 | } 211 | }, 212 | "node_modules/whatwg-url": { 213 | "version": "13.0.0", 214 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", 215 | "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", 216 | "dependencies": { 217 | "tr46": "^4.1.1", 218 | "webidl-conversions": "^7.0.0" 219 | }, 220 | "engines": { 221 | "node": ">=16" 222 | } 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /5. mongodb-basics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "5.-mongodb-basics", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "mongoose": "^8.7.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /6. bookstore-api/controllers/book-controller.js: -------------------------------------------------------------------------------- 1 | const Book = require("../models/book"); 2 | 3 | const getAllBooks = async (req, res) => { 4 | try { 5 | const allBooks = await Book.find({}); 6 | if (allBooks?.length > 0) { 7 | res.status(200).json({ 8 | success: true, 9 | message: "List of books fetched successfully", 10 | data: allBooks, 11 | }); 12 | } else { 13 | res.status(404).json({ 14 | success: false, 15 | message: "Bo books found in collection", 16 | }); 17 | } 18 | } catch (e) { 19 | console.log(e); 20 | res.status(500).json({ 21 | success: false, 22 | message: "Something went wrong! Please try again", 23 | }); 24 | } 25 | }; 26 | 27 | const getSingleBookById = async (req, res) => { 28 | try { 29 | const getCurrentBookID = req.params.id; 30 | const bookDetailsByID = await Book.findById(getCurrentBookID); 31 | 32 | if (!bookDetailsByID) { 33 | return res.status(404).json({ 34 | success: false, 35 | message: 36 | "Book with the current ID is not found! Please try with a different ID", 37 | }); 38 | } 39 | 40 | res.status(200).json({ 41 | success: true, 42 | data: bookDetailsByID, 43 | }); 44 | } catch (e) { 45 | console.log(e); 46 | res.status(500).json({ 47 | success: false, 48 | message: "Something went wrong! Please try again", 49 | }); 50 | } 51 | }; 52 | 53 | const addNewBook = async (req, res) => { 54 | try { 55 | const newBookFormData = req.body; 56 | const newlyCreatedBook = await Book.create(newBookFormData); 57 | if (newBookFormData) { 58 | res.status(201).json({ 59 | success: true, 60 | message: "Book added successfully", 61 | data: newlyCreatedBook, 62 | }); 63 | } 64 | } catch (e) { 65 | console.log(e); 66 | res.status(500).json({ 67 | success: false, 68 | message: "Something went wrong! Please try again", 69 | }); 70 | } 71 | }; 72 | 73 | const updateBook = async (req, res) => { 74 | try { 75 | const updatedBookFormData = req.body; 76 | const getCurrentBookID = req.params.id; 77 | const updatedBook = await Book.findByIdAndUpdate( 78 | getCurrentBookID, 79 | updatedBookFormData, 80 | { 81 | new: true, 82 | } 83 | ); 84 | 85 | if (!updatedBook) { 86 | res.status(404).json({ 87 | success: false, 88 | message: "Book is not found with this ID", 89 | }); 90 | } 91 | 92 | res.status(200).json({ 93 | success: true, 94 | message: "Book updated successfully", 95 | data: updatedBook, 96 | }); 97 | } catch (e) { 98 | console.log(e); 99 | res.status(500).json({ 100 | success: false, 101 | message: "Something went wrong! Please try again", 102 | }); 103 | } 104 | }; 105 | 106 | const deleteBook = async (req, res) => { 107 | try { 108 | const getCurrentBookID = req.params.id; 109 | const deletedBook = await Book.findByIdAndDelete(getCurrentBookID); 110 | 111 | if (!deletedBook) { 112 | res.status(404).json({ 113 | success: false, 114 | message: "Book is not found with this ID", 115 | }); 116 | } 117 | 118 | res.status(200).json({ 119 | success: true, 120 | data: deletedBook, 121 | }); 122 | } catch (e) { 123 | console.log(e); 124 | res.status(500).json({ 125 | success: false, 126 | message: "Something went wrong! Please try again", 127 | }); 128 | } 129 | }; 130 | 131 | module.exports = { 132 | getAllBooks, 133 | getSingleBookById, 134 | addNewBook, 135 | updateBook, 136 | deleteBook, 137 | }; 138 | -------------------------------------------------------------------------------- /6. bookstore-api/database/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const connectToDB = async () => { 4 | try { 5 | await mongoose.connect( 6 | "mongodb+srv://sangammukherjee2022:sangammukherjee2025@cluster0.mohg0.mongodb.net/" 7 | ); 8 | console.log("mongodb is connected successfully !"); 9 | } catch (error) { 10 | console.error("Mongodb connection failed", error); 11 | process.exit(1); 12 | } 13 | }; 14 | 15 | module.exports = connectToDB; 16 | -------------------------------------------------------------------------------- /6. bookstore-api/models/book.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const BookSchema = new mongoose.Schema({ 4 | title: { 5 | type: String, 6 | required: [true, "Book title is required"], 7 | trim: true, 8 | maxLength: [100, "Book title can not be more than 100 characters"], 9 | }, 10 | author: { 11 | type: String, 12 | required: [true, "Author name is required"], 13 | trim: true, 14 | }, 15 | year: { 16 | type: Number, 17 | required: [true, "Publication year is required"], 18 | min: [1000, "Year must be atleast 1000"], 19 | max: [new Date().getFullYear(), "Year cannot be in the future"], 20 | }, 21 | createdAt: { 22 | type: Date, 23 | default: Date.now, 24 | }, 25 | }); 26 | 27 | module.exports = mongoose.model("Book", BookSchema); 28 | -------------------------------------------------------------------------------- /6. bookstore-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "6.-bookstore-api", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "server.js", 9 | "dev": "nodemon server.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "nodemon": "^3.1.7" 16 | }, 17 | "dependencies": { 18 | "dotenv": "^16.4.5", 19 | "express": "^4.21.1", 20 | "mongoose": "^8.7.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /6. bookstore-api/routes/book-routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { 3 | getAllBooks, 4 | getSingleBookById, 5 | updateBook, 6 | deleteBook, 7 | addNewBook, 8 | } = require("../controllers/book-controller"); 9 | 10 | //create express router 11 | const router = express.Router(); 12 | 13 | //all routes that are related to books only 14 | router.get("/get", getAllBooks); 15 | router.get("/get/:id", getSingleBookById); 16 | router.post("/add", addNewBook); 17 | router.put("/update/:id", updateBook); 18 | router.delete("/delete/:id", deleteBook); 19 | 20 | module.exports = router; 21 | -------------------------------------------------------------------------------- /6. bookstore-api/server.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const express = require("express"); 3 | const connectToDB = require("./database/db"); 4 | const bookRoutes = require("./routes/book-routes"); 5 | 6 | const app = express(); 7 | const PORT = process.env.PORT || 3000; 8 | 9 | //connect to our database 10 | connectToDB(); 11 | 12 | //middleware -> express.json() 13 | app.use(express.json()); 14 | 15 | //routes here 16 | app.use("/api/books", bookRoutes); 17 | 18 | app.listen(PORT, () => { 19 | console.log(`Server is now running on port ${PORT}`); 20 | }); 21 | -------------------------------------------------------------------------------- /7. nodejs-auth/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /7. nodejs-auth/config/cloudinary.js: -------------------------------------------------------------------------------- 1 | const cloudinary = require("cloudinary").v2; 2 | 3 | cloudinary.config({ 4 | cloud_name: process.env.CLOUDINARY_CLOUD_NAME, 5 | api_key: process.env.CLOUDINARY_API_KEY, 6 | api_secret: process.env.CLOUDINARY_API_SECRET, 7 | }); 8 | 9 | module.exports = cloudinary; 10 | -------------------------------------------------------------------------------- /7. nodejs-auth/controllers/auth-controller.js: -------------------------------------------------------------------------------- 1 | const User = require("../models/User"); 2 | const bcrypt = require("bcryptjs"); 3 | const jwt = require("jsonwebtoken"); 4 | 5 | //register controller 6 | const registerUser = async (req, res) => { 7 | try { 8 | //extract user information from our request body 9 | const { username, email, password, role } = req.body; 10 | 11 | //check if the user is already exists in our database 12 | const checkExistingUser = await User.findOne({ 13 | $or: [{ username }, { email }], 14 | }); 15 | if (checkExistingUser) { 16 | return res.status(400).json({ 17 | success: false, 18 | message: 19 | "User is already exists either with same username or same email. Please try with a different username or email", 20 | }); 21 | } 22 | 23 | //hash user password 24 | const salt = await bcrypt.genSalt(10); 25 | const hashedPassword = await bcrypt.hash(password, salt); 26 | 27 | //create a new user and save in your database 28 | const newlyCreatedUser = new User({ 29 | username, 30 | email, 31 | password: hashedPassword, 32 | role: role || "user", 33 | }); 34 | 35 | await newlyCreatedUser.save(); 36 | 37 | if (newlyCreatedUser) { 38 | res.status(201).json({ 39 | success: true, 40 | message: "User registered successfully!", 41 | }); 42 | } else { 43 | res.status(400).json({ 44 | success: false, 45 | message: "Unable to register user! please try again.", 46 | }); 47 | } 48 | } catch (e) { 49 | console.log(e); 50 | res.status(500).json({ 51 | success: false, 52 | message: "Some error occured! Please try again", 53 | }); 54 | } 55 | }; 56 | 57 | //login controller 58 | 59 | const loginUser = async (req, res) => { 60 | try { 61 | const { username, password } = req.body; 62 | 63 | //find if the current user is exists in database or not 64 | const user = await User.findOne({ username }); 65 | 66 | if (!user) { 67 | return res.status(400).json({ 68 | success: false, 69 | message: `User doesn't exists`, 70 | }); 71 | } 72 | //if the password is correct or not 73 | const isPasswordMatch = await bcrypt.compare(password, user.password); 74 | 75 | if (!isPasswordMatch) { 76 | return res.status(400).json({ 77 | success: false, 78 | message: "Invalid credentials!", 79 | }); 80 | } 81 | 82 | //create user token 83 | const accessToken = jwt.sign( 84 | { 85 | userId: user._id, 86 | username: user.username, 87 | role: user.role, 88 | }, 89 | process.env.JWT_SECRET_KEY, 90 | { 91 | expiresIn: "30m", 92 | } 93 | ); 94 | 95 | res.status(200).json({ 96 | success: true, 97 | message: "Logged in successful", 98 | accessToken, 99 | }); 100 | } catch (e) { 101 | console.log(e); 102 | res.status(500).json({ 103 | success: false, 104 | message: "Some error occured! Please try again", 105 | }); 106 | } 107 | }; 108 | 109 | const changePassword = async (req, res) => { 110 | try { 111 | const userId = req.userInfo.userId; 112 | 113 | //extract old and new password; 114 | const { oldPassword, newPassword } = req.body; 115 | 116 | //find the current logged in user 117 | const user = await User.findById(userId); 118 | 119 | if (!user) { 120 | return res.status(400).json({ 121 | success: false, 122 | message: "User not found", 123 | }); 124 | } 125 | 126 | //check if the old password is correct 127 | const isPasswordMatch = await bcrypt.compare(oldPassword, user.password); 128 | 129 | if (!isPasswordMatch) { 130 | return res.status(400).json({ 131 | success: false, 132 | message: "Old password is not correct! Please try again.", 133 | }); 134 | } 135 | 136 | //hash the new password here 137 | const salt = await bcrypt.genSalt(10); 138 | const newHashedPassword = await bcrypt.hash(newPassword, salt); 139 | 140 | //update user password 141 | user.password = newHashedPassword; 142 | await user.save(); 143 | 144 | res.status(200).json({ 145 | success: true, 146 | message: "Password changed successfully", 147 | }); 148 | } catch (e) { 149 | console.log(e); 150 | res.status(500).json({ 151 | success: false, 152 | message: "Some error occured! Please try again", 153 | }); 154 | } 155 | }; 156 | 157 | module.exports = { registerUser, loginUser, changePassword }; 158 | -------------------------------------------------------------------------------- /7. nodejs-auth/controllers/image-controller.js: -------------------------------------------------------------------------------- 1 | const Image = require("../models/Image"); 2 | const { uploadToCloudinary } = require("../helpers/cloudinaryHelper"); 3 | const fs = require("fs"); 4 | const cloudinary = require("../config/cloudinary"); 5 | 6 | const uploadImageController = async (req, res) => { 7 | try { 8 | //check if file is missing in req object 9 | if (!req.file) { 10 | return res.status(400).json({ 11 | success: false, 12 | message: "File is required. Please upload an image", 13 | }); 14 | } 15 | 16 | //upload to cloudinary 17 | const { url, publicId } = await uploadToCloudinary(req.file.path); 18 | 19 | //store the image url and public id along with the uploaded user id in database 20 | const newlyUploadedImage = new Image({ 21 | url, 22 | publicId, 23 | uploadedBy: req.userInfo.userId, 24 | }); 25 | 26 | await newlyUploadedImage.save(); 27 | 28 | //delete the file from local stroage 29 | // fs.unlinkSync(req.file.path); 30 | 31 | res.status(201).json({ 32 | success: true, 33 | message: "Imaged uploaded successfully", 34 | image: newlyUploadedImage, 35 | }); 36 | } catch (error) { 37 | console.log(error); 38 | res.status(500).json({ 39 | success: false, 40 | message: "Something went wrong! Please try again", 41 | }); 42 | } 43 | }; 44 | 45 | const fetchImagesController = async (req, res) => { 46 | try { 47 | const page = parseInt(req.query.page) || 1; 48 | const limit = parseInt(req.query.limit) || 2; 49 | const skip = (page - 1) * limit; 50 | 51 | const sortBy = req.query.sortBy || "createdAt"; 52 | const sortOrder = req.query.sortOrder === "asc" ? 1 : -1; 53 | const totalImages = await Image.countDocuments(); 54 | const totalPages = Math.ceil(totalImages / limit); 55 | 56 | const sortObj = {}; 57 | sortObj[sortBy] = sortOrder; 58 | const images = await Image.find().sort(sortObj).skip(skip).limit(limit); 59 | 60 | if (images) { 61 | res.status(200).json({ 62 | success: true, 63 | currentPage: page, 64 | totalPages: totalPages, 65 | totalImages: totalImages, 66 | data: images, 67 | }); 68 | } 69 | } catch (error) { 70 | console.log(error); 71 | res.status(500).json({ 72 | success: false, 73 | message: "Something went wrong! Please try again", 74 | }); 75 | } 76 | }; 77 | 78 | const deleteImageController = async (req, res) => { 79 | try { 80 | const getCurrentIdOfImageToBeDeleted = req.params.id; 81 | const userId = req.userInfo.userId; 82 | 83 | const image = await Image.findById(getCurrentIdOfImageToBeDeleted); 84 | 85 | if (!image) { 86 | return res.status(404).json({ 87 | success: false, 88 | message: "Image not found", 89 | }); 90 | } 91 | 92 | //check if this image is uploaded by the current user who is trying to delete this image 93 | if (image.uploadedBy.toString() !== userId) { 94 | return res.status(403).json({ 95 | success: false, 96 | message: `You are not authorized to delete this image because you haven't uploaded it`, 97 | }); 98 | } 99 | 100 | //delete this image first from your cloudinary stroage 101 | await cloudinary.uploader.destroy(image.publicId); 102 | 103 | //delete this image from mongodb database 104 | await Image.findByIdAndUpdate(getCurrentIdOfImageToBeDeleted); 105 | 106 | res.status(200).json({ 107 | success: true, 108 | message: "Image deleted successfully", 109 | }); 110 | } catch (error) { 111 | console.log(error); 112 | res.status(500).json({ 113 | success: false, 114 | message: "Something went wrong! Please try again", 115 | }); 116 | } 117 | }; 118 | 119 | module.exports = { 120 | uploadImageController, 121 | fetchImagesController, 122 | deleteImageController, 123 | }; 124 | -------------------------------------------------------------------------------- /7. nodejs-auth/database/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const connectToDB = async () => { 4 | try { 5 | await mongoose.connect(process.env.MONGO_URI); 6 | console.log("MongoDB connected successfully"); 7 | } catch (e) { 8 | console.error("MongoDB connection failed"); 9 | process.exit(1); 10 | } 11 | }; 12 | 13 | module.exports = connectToDB; 14 | -------------------------------------------------------------------------------- /7. nodejs-auth/helpers/cloudinaryHelper.js: -------------------------------------------------------------------------------- 1 | const cloudinary = require("../config/cloudinary"); 2 | 3 | const uploadToCloudinary = async (filePath) => { 4 | try { 5 | const result = await cloudinary.uploader.upload(filePath); 6 | 7 | return { 8 | url: result.secure_url, 9 | publicId: result.public_id, 10 | }; 11 | } catch (error) { 12 | console.error("Error while uploading to cloudinary", error); 13 | throw new Error("Error while uploading to cloudinary"); 14 | } 15 | }; 16 | 17 | module.exports = { 18 | uploadToCloudinary, 19 | }; 20 | -------------------------------------------------------------------------------- /7. nodejs-auth/middleware/admin-middleware.js: -------------------------------------------------------------------------------- 1 | const isAdminUser = (req, res, next) => { 2 | if (req.userInfo.role !== "admin") { 3 | return res.status(403).json({ 4 | success: false, 5 | message: "Access denied! Admin rights required.", 6 | }); 7 | } 8 | 9 | next(); 10 | }; 11 | 12 | module.exports = isAdminUser; 13 | -------------------------------------------------------------------------------- /7. nodejs-auth/middleware/auth-middleware.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | 3 | const authMiddleware = (req, res, next) => { 4 | const authHeader = req.headers["authorization"]; 5 | console.log(authHeader); 6 | const token = authHeader && authHeader.split(" ")[1]; 7 | 8 | if (!token) { 9 | return res.status(401).json({ 10 | success: false, 11 | message: "Access denied. No token provided. Please login to continue", 12 | }); 13 | } 14 | 15 | //decode this token 16 | try { 17 | const decodedTokenInfo = jwt.verify(token, process.env.JWT_SECRET_KEY); 18 | console.log(decodedTokenInfo); 19 | 20 | req.userInfo = decodedTokenInfo; 21 | next(); 22 | } catch (error) { 23 | return res.status(500).json({ 24 | success: false, 25 | message: "Access denied. No token provided. Please login to continue", 26 | }); 27 | } 28 | }; 29 | 30 | module.exports = authMiddleware; 31 | -------------------------------------------------------------------------------- /7. nodejs-auth/middleware/upload-middleware.js: -------------------------------------------------------------------------------- 1 | const multer = require("multer"); 2 | const path = require("path"); 3 | 4 | //set our multer storage 5 | const storage = multer.diskStorage({ 6 | destination: function (req, file, cb) { 7 | cb(null, "uploads/"); 8 | }, 9 | filename: function (req, file, cb) { 10 | cb( 11 | null, 12 | 13 | file.fieldname + "-" + Date.now() + path.extname(file.originalname) 14 | ); 15 | }, 16 | }); 17 | 18 | //file filter function 19 | const checkFileFilter = (req, file, cb) => { 20 | if (file.mimetype.startsWith("image")) { 21 | cb(null, true); 22 | } else { 23 | cb(new Error("Not an image! Please upload only images")); 24 | } 25 | }; 26 | 27 | //multer middleware 28 | module.exports = multer({ 29 | storage: storage, 30 | fileFilter: checkFileFilter, 31 | limits: { 32 | fileSize: 5 * 1024 * 1024, //5MB file size limit 33 | }, 34 | }); 35 | -------------------------------------------------------------------------------- /7. nodejs-auth/models/Image.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const ImageSchema = new mongoose.Schema( 4 | { 5 | url: { 6 | type: String, 7 | required: true, 8 | }, 9 | 10 | publicId: { 11 | type: String, 12 | required: true, 13 | }, 14 | uploadedBy: { 15 | type: mongoose.Schema.Types.ObjectId, 16 | ref: "User", 17 | required: true, 18 | }, 19 | }, 20 | { timestamps: true } 21 | ); 22 | 23 | module.exports = mongoose.model("Image", ImageSchema); 24 | -------------------------------------------------------------------------------- /7. nodejs-auth/models/User.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const UserSchema = new mongoose.Schema( 4 | { 5 | username: { 6 | type: String, 7 | required: true, 8 | unique: true, 9 | trim: true, 10 | }, 11 | email: { 12 | type: String, 13 | required: true, 14 | unique: true, 15 | trim: true, 16 | lowercase: true, 17 | }, 18 | password: { 19 | type: String, 20 | required: true, 21 | }, 22 | role: { 23 | type: String, 24 | enum: ["user", "admin"], // only allow 'user' or 'admin' roles 25 | default: "user", 26 | }, 27 | }, 28 | { timestamps: true } 29 | ); 30 | 31 | module.exports = mongoose.model("User", UserSchema); 32 | -------------------------------------------------------------------------------- /7. nodejs-auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "7.-nodejs-auth", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "node server.js", 8 | "dev": "nodemon server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "bcryptjs": "^2.4.3", 15 | "cloudinary": "^2.5.1", 16 | "dotenv": "^16.4.5", 17 | "express": "^4.21.1", 18 | "jsonwebtoken": "^9.0.2", 19 | "mongoose": "^8.7.2", 20 | "multer": "^1.4.5-lts.1" 21 | }, 22 | "devDependencies": { 23 | "nodemon": "^3.1.7" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /7. nodejs-auth/routes/admin-routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const authMiddleware = require("../middleware/auth-middleware"); 3 | const adminMiddleware = require("../middleware/admin-middleware"); 4 | 5 | const router = express.Router(); 6 | 7 | router.get("/welcome", authMiddleware, adminMiddleware, (req, res) => { 8 | res.json({ 9 | message: "Welcome to the admin page", 10 | }); 11 | }); 12 | 13 | module.exports = router; 14 | -------------------------------------------------------------------------------- /7. nodejs-auth/routes/auth-routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { 3 | registerUser, 4 | loginUser, 5 | changePassword, 6 | } = require("../controllers/auth-controller"); 7 | const router = express.Router(); 8 | const authMiddleware = require("../middleware/auth-middleware"); 9 | 10 | //all routes are related to authentication & authorization 11 | router.post("/register", registerUser); 12 | router.post("/login", loginUser); 13 | router.post("/change-password", authMiddleware, changePassword); 14 | 15 | module.exports = router; 16 | -------------------------------------------------------------------------------- /7. nodejs-auth/routes/home-routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const authMiddleware = require("../middleware/auth-middleware"); 3 | const router = express.Router(); 4 | 5 | router.get("/welcome", authMiddleware, (req, res) => { 6 | const { username, userId, role } = req.userInfo; 7 | 8 | res.json({ 9 | message: "Welcome to the home page", 10 | user: { 11 | _id: userId, 12 | username, 13 | role, 14 | }, 15 | }); 16 | }); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /7. nodejs-auth/routes/image-routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const authMiddleware = require("../middleware/auth-middleware"); 3 | const adminMiddleware = require("../middleware/admin-middleware"); 4 | const uploadMiddleware = require("../middleware/upload-middleware"); 5 | const { 6 | uploadImageController, 7 | fetchImagesController, 8 | deleteImageController, 9 | } = require("../controllers/image-controller"); 10 | 11 | const router = express.Router(); 12 | 13 | //upload the image 14 | router.post( 15 | "/upload", 16 | authMiddleware, 17 | adminMiddleware, 18 | uploadMiddleware.single("image"), 19 | uploadImageController 20 | ); 21 | 22 | //to get all the images 23 | router.get("/get", authMiddleware, fetchImagesController); 24 | 25 | //delete image route 26 | router.delete("/:id", authMiddleware, adminMiddleware, deleteImageController); 27 | 28 | module.exports = router; 29 | -------------------------------------------------------------------------------- /7. nodejs-auth/server.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const express = require("express"); 3 | const connectToDB = require("./database/db"); 4 | const authRoutes = require("./routes/auth-routes"); 5 | const homeRoutes = require("./routes/home-routes"); 6 | const adminRoutes = require("./routes/admin-routes"); 7 | const uploadImageRoutes = require("./routes/image-routes"); 8 | 9 | connectToDB(); 10 | 11 | const app = express(); 12 | const PORT = process.env.PORT || 3000; 13 | 14 | //Middlewares 15 | app.use(express.json()); 16 | 17 | app.use("/api/auth", authRoutes); 18 | app.use("/api/home", homeRoutes); 19 | app.use("/api/admin", adminRoutes); 20 | app.use("/api/image", uploadImageRoutes); 21 | 22 | app.listen(PORT, () => { 23 | console.log(`Server is now listeining to PORT ${PORT}`); 24 | }); 25 | -------------------------------------------------------------------------------- /7. nodejs-auth/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | { 5 | "src": "server.js", 6 | "use": "@vercel/node" 7 | } 8 | ], 9 | "routes": [ 10 | { 11 | "src": "/(.*)", 12 | "dest": "server.js" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/controllers/book-controller.js: -------------------------------------------------------------------------------- 1 | const Author = require("../models/Author"); 2 | const Book = require("../models/Book"); 3 | 4 | const createAuthor = async (req, res) => { 5 | try { 6 | const author = new Author(req.body); 7 | await author.save(); 8 | 9 | res.status(201).json({ 10 | success: true, 11 | data: author, 12 | }); 13 | } catch (e) { 14 | console.log(e); 15 | res.status(500).json({ 16 | success: false, 17 | message: "Some error occured", 18 | }); 19 | } 20 | }; 21 | 22 | const createBook = async (req, res) => { 23 | try { 24 | const book = new Book(req.body); 25 | await book.save(); 26 | 27 | res.status(201).json({ 28 | success: true, 29 | data: book, 30 | }); 31 | } catch (e) { 32 | console.log(e); 33 | res.status(500).json({ 34 | success: false, 35 | message: "Some error occured", 36 | }); 37 | } 38 | }; 39 | 40 | const getBookWithAuthor = async (req, res) => { 41 | try { 42 | const book = await Book.findById(req.params.id).populate("author"); 43 | 44 | if (!book) { 45 | return res.status(404).json({ 46 | success: false, 47 | message: "Book not found!", 48 | }); 49 | } 50 | 51 | res.status(200).json({ 52 | success: true, 53 | data: book, 54 | }); 55 | } catch (e) { 56 | console.log(e); 57 | res.status(500).json({ 58 | success: false, 59 | message: "Some error occured", 60 | }); 61 | } 62 | }; 63 | 64 | module.exports = { createAuthor, createBook, getBookWithAuthor }; 65 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/controllers/product-controller.js: -------------------------------------------------------------------------------- 1 | const Product = require("../models/Product"); 2 | 3 | const getProductStats = async (req, res) => { 4 | try { 5 | const result = await Product.aggregate([ 6 | //stage 1 7 | { 8 | $match: { 9 | inStock: true, 10 | price: { 11 | $gte: 100, 12 | }, 13 | }, 14 | }, 15 | //stage 2 : group documents 16 | { 17 | $group: { 18 | _id: "$category", 19 | avgPrice: { 20 | $avg: "$price", 21 | }, 22 | count: { 23 | $sum: 1, 24 | }, 25 | }, 26 | }, 27 | ]); 28 | 29 | res.status(200).json({ 30 | success: true, 31 | data: result, 32 | }); 33 | } catch (e) { 34 | console.log(e); 35 | res.status(500).json({ 36 | success: false, 37 | message: "Some error occured!", 38 | }); 39 | } 40 | }; 41 | 42 | const getProductAnalysis = async (req, res) => { 43 | try { 44 | const result = await Product.aggregate([ 45 | { 46 | $match: { 47 | category: "Electronics", 48 | }, 49 | }, 50 | { 51 | $group: { 52 | _id: null, 53 | totalRevenue: { 54 | $sum: "$price", 55 | }, 56 | averagePrice: { 57 | $avg: "$price", 58 | }, 59 | maxProductPrice: { 60 | $max: "$price", 61 | }, 62 | minProductPrice: { 63 | $min: "$price", 64 | }, 65 | }, 66 | }, 67 | { 68 | $project: { 69 | _id: 0, 70 | totalRevenue: 1, 71 | averagePrice: 1, 72 | maxProductPrice: 1, 73 | minProductPrice: 1, 74 | priceRange: { 75 | $subtract: ["$maxProductPrice", "$minProductPrice"], 76 | }, 77 | }, 78 | }, 79 | ]); 80 | 81 | res.status(200).json({ 82 | success: true, 83 | data: result, 84 | }); 85 | } catch (e) { 86 | res.status(500).json({ 87 | success: false, 88 | message: "Some error occured!", 89 | }); 90 | } 91 | }; 92 | 93 | const insertSampleProducts = async (req, res) => { 94 | try { 95 | const sampleProducts = [ 96 | { 97 | name: "Laptop", 98 | category: "Electronics", 99 | price: 999, 100 | inStock: true, 101 | tags: ["computer", "tech"], 102 | }, 103 | { 104 | name: "Smartphone", 105 | category: "Electronics", 106 | price: 699, 107 | inStock: true, 108 | tags: ["mobile", "tech"], 109 | }, 110 | { 111 | name: "Headphones", 112 | category: "Electronics", 113 | price: 199, 114 | inStock: false, 115 | tags: ["audio", "tech"], 116 | }, 117 | { 118 | name: "Running Shoes", 119 | category: "Sports", 120 | price: 89, 121 | inStock: true, 122 | tags: ["footwear", "running"], 123 | }, 124 | { 125 | name: "Novel", 126 | category: "Books", 127 | price: 15, 128 | inStock: true, 129 | tags: ["fiction", "bestseller"], 130 | }, 131 | ]; 132 | const result = await Product.insertMany(sampleProducts); 133 | res.status(201).json({ 134 | succes: true, 135 | data: `Inserted ${result.length} sample products`, 136 | }); 137 | } catch (e) { 138 | console.log(e); 139 | res.status(500).json({ 140 | success: false, 141 | message: "Some error occured!", 142 | }); 143 | } 144 | }; 145 | 146 | module.exports = { insertSampleProducts, getProductStats, getProductAnalysis }; 147 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/models/Author.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const AuthorSchema = new mongoose.Schema({ 4 | name: String, 5 | bio: String, 6 | }); 7 | 8 | module.exports = mongoose.model("Author", AuthorSchema); 9 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/models/Book.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const BookSchema = new mongoose.Schema({ 4 | title: String, 5 | author: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | ref: "Author", 8 | }, 9 | }); 10 | 11 | module.exports = mongoose.model("Book", BookSchema); 12 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/models/Product.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const ProductSchema = new mongoose.Schema({ 4 | name: String, 5 | category: String, 6 | price: Number, 7 | inStock: Boolean, 8 | tags: [String], 9 | }); 10 | 11 | module.exports = mongoose.model("Product", ProductSchema); 12 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "8.-mongodb-intermediate", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "server.js", 9 | "dev": "nodemon server.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "dotenv": "^16.4.5", 16 | "express": "^4.21.1", 17 | "mongoose": "^8.7.3" 18 | }, 19 | "devDependencies": { 20 | "nodemon": "^3.1.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/routes/book-routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { 3 | createAuthor, 4 | createBook, 5 | getBookWithAuthor, 6 | } = require("../controllers/book-controller"); 7 | 8 | const router = express.Router(); 9 | 10 | router.post("/author", createAuthor); 11 | router.post("/book", createBook); 12 | router.get("/book/:id", getBookWithAuthor); 13 | 14 | module.exports = router; 15 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/routes/product-routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { 3 | insertSampleProducts, 4 | getProductStats, 5 | getProductAnalysis, 6 | } = require("../controllers/product-controller"); 7 | 8 | const router = express.Router(); 9 | 10 | router.post("/add", insertSampleProducts); 11 | router.get("/stats", getProductStats); 12 | router.get("/analysis", getProductAnalysis); 13 | 14 | module.exports = router; 15 | -------------------------------------------------------------------------------- /8. mongodb-intermediate/server.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const express = require("express"); 3 | const mongoose = require("mongoose"); 4 | const productRoutes = require("./routes/product-routes"); 5 | const bookRoutes = require("./routes/book-routes"); 6 | 7 | const app = express(); 8 | 9 | //connect to our database 10 | mongoose 11 | .connect(process.env.MONGO_URI) 12 | .then(() => console.log("mongodb connected successfully")) 13 | .catch((e) => console.log(e)); 14 | 15 | //use middlewares 16 | app.use(express.json()); 17 | 18 | app.use("/products", productRoutes); 19 | app.use("/reference", bookRoutes); 20 | 21 | app.listen(process.env.PORT, () => { 22 | console.log(`Server is now running on port ${process.env.PORT}`); 23 | }); 24 | -------------------------------------------------------------------------------- /9. nodejs-socket/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "9.-nodejs-socket", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "express": "^4.21.1", 15 | "socket.io": "^4.8.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /9. nodejs-socket/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Chat App 7 | 8 | 9 |
10 |

Online Users

11 |
    12 |
    13 |
    14 |
    15 | 21 | 22 |
    23 | 24 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /9. nodejs-socket/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const http = require("http"); 3 | const socketIo = require("socket.io"); 4 | 5 | const app = express(); 6 | 7 | const server = http.createServer(app); 8 | 9 | //initiate socket.io and attch this to the http server 10 | const io = socketIo(server); 11 | 12 | app.use(express.static("public")); 13 | 14 | const users = new Set(); 15 | 16 | io.on("connection", (socket) => { 17 | console.log("A user is now connected"); 18 | 19 | //handle users when they will join the chat 20 | socket.on("join", (userName) => { 21 | users.add(userName); 22 | socket.userName = userName; 23 | 24 | //broadcast to all clients/users that a new user has joined 25 | io.emit("userJoined", userName); 26 | 27 | //Send the updated user list to all clients 28 | io.emit("userList", Array.from(users)); 29 | }); 30 | 31 | //handle incoming chat message 32 | socket.on("chatMessage", (message) => { 33 | //broadcast the received message to all connected clients 34 | io.emit("chatMessage", message); 35 | }); 36 | 37 | //handle user disconnection 38 | socket.on("disconnect", () => { 39 | console.log("An User is disconnected", socket.userName); 40 | 41 | users.forEach((user) => { 42 | if (user === socket.userName) { 43 | users.delete(user); 44 | 45 | io.emit("userLeft", user); 46 | 47 | io.emit("userList", Array.from(users)); 48 | } 49 | }); 50 | }); 51 | }); 52 | 53 | const PORT = 3000; 54 | server.listen(PORT, () => { 55 | console.log(`Server is now running on http://localhost:${PORT}`); 56 | }); 57 | --------------------------------------------------------------------------------