Javascript code executes inside browser.
Browser has javascript engine which executes the javascript code.
Javascript Engine presents only inside Browser.
Each broswer has different Javascript engines.
Chrome -> V8 Engine
Fierfox -> Spider Monkey
Safari -> Nitro
The most populor engine is V8 engine.
A scientist Ryan Dahl taken the V8 engine and embedded with C++ code.And named this project as NodeJS
.
- You can run JS outside of the browser.
- Javascript can talk to native machine beacause of C++.
- You can create webservers in Javascript language.
NodeJs is neither a framework or language . NodeJS is a Runtime Environment for javascript.
Ex:
PS C:\Users\ayush> node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> console.log("Hello");
Hello
undefined
> 2+2
4
>
-
Go to official website
nodejs.org
-
Select LTS Version of NodeJS.
LTS - Long Term Support , Start with even number (Stable realese - can be used in production)Beta(Current) - Bugs , Unstability , start with odd number
-
Intall in your local computer and add the path
C:\Program Files\nodejs
to your environment variable. -
Open Terminal and write command
PS C:\Users\ayush> node --version v20.10.0 PS C:\Users\ayush>
-
If giving this output then NodeJS Installed Succesfully.
NPM -> Node Package Manager. We can manage package through it.
/**
* Split your code into different files and folders.
* All maths related function will be written in math.js
*
* To use the math.js file in other file
* --------------------------------------
* use require -> const name = require('filename')
*
*/
const buffer = require('buffer') // built in package
const math = require('./math')
//De-structuring -> we can directlly use add and sub function
const {add , sub } = require('./math')
console.log("Math Add value is : ",math.add(2 , 4));
console.log("Math Subtract value is : ",math.sub(2 , 4));
console.log("\nUsing destructured function \n")
console.log("Math Add value is : ",add(2 , 4));
console.log("Math Subtract value is : ",sub(2 , 4));
function add(a , b){
return a + b
}
function sub(a , b){
return a - b;
}
// module.exports = add;
// module.exports = sub ; // overiding the value
// we can use object to export multiple values
// multi exports
module.exports = {
add ,
sub,
}
//exporting anonymous function
// exports.add = (a , b) => a + b;
// exports.sub = ( a , b) => a - b;
const fs = require('fs')
//used this fs module to intract with files
//creating a file (Synchronous call)
// fs.writeFileSync("./test.txt" , 'Hey There');
//Async
// fs.writeFile("./test.txt" , "Hello World", (err) => {})
//Reading the file
// Sync.. -> returns the result
// const result = fs.readFileSync("./contacts.txt" , "utf-8");
// console.log(result);
//Async.. -> return nothing , we have to pass a callback
// fs.readFile("./contacts.txt" , "utf-8" , (err , result)=>{
// if(err){
// console.log("Error",err);
// }else{
// console.log(result);
// }
// });
// Appending the text
// fs.appendFileSync("./test.txt" , "\nHey there I am appended");
// Copy the file
// fs.cpSync("./test.txt" , "./copy.txt");
// Delete the file
// fs.unlinkSync("./copy.txt");
// Cheking status of file
// console.log(fs.statSync("./test.txt"));
//making directory
// fs.mkdirSync("my-docs");
fs.mkdirSync("my-docs/a/b" , { recursive:true});
Client ----------> Server
Request (NodeJs)
Request made to server. Node js has event queue.
Firstly requests are queued into event queue .
Now even loop is a machine which always watches the event queue.
If event loop get any request in event queue the select that request using fifo(first in first out) principle.
Request can be of two types :
- Blocking Operations (Sync.. task)
- Non- Blockinng Operations (Async.. task)
If the request has non-blocking operation
then the server process it and sends the response back to the user.
If the request has blocking operation
then to resolve this request it goes to thread pool.
Thread pool is a pool of threads . Threads act a worker which work for you . It is resposible for fuilful your blocking operation. If the works completes then it return the result . Then the respose is send back to the user .
const http = require("http");
const fs = require("fs");
const myServer = http.createServer((req , res)=>{
const log = `${Date.now()} : ${req.url} : New Request Recieved \n`;
fs.appendFile('log.txt' , log , (err , data)=>{
switch(req.url){
case '/' : res.end("Home Page");
break;
case '/about' : res.end("I am Ayush");
break;
default:
res.end("404 Not Found")
}
})
// console.log(req.headers)
// console.log(req)
});
const PORT = 8000;
myServer.listen(8000, ()=>{
console.log(`Server started at port no ${PORT} `);
})
Uniform Resource Locator
https:// www.ayush.dev/
-------- --------------
Protocol Domain - User friendly name
of IP Address of My Server
dev/ -> Path
ayush.dev/project/1 -> Nested Path
ayush.dev/about?userID=1&a=2 -> Query parameter
Protocol: Set of rules that tells browser how to communicate to the browser.
https -> Hypertext Transfer Protocol Secure
GET -> When you want to get some data from the server.
POST -> When you want to send and mutate some data in server.
PUT
PATCH
DELETE
const http = require("http");
const fs = require("fs");
const url = require("url");
const myServer = http.createServer((req , res)=>{
if(req.url === '/favicon.ico') return res.end();
const log = `${Date.now()} : ${req.url} : New Request Recieved \n`;
const myUrl = url.parse(req.url , true);
console.log(myUrl);
fs.appendFile('log.txt' , log , (err , data)=>{
switch(myUrl.pathname){
case '/' :
if(req.method == 'GET') res.end("Home Page");
break;
case '/about' :
//query parameter
const username = myUrl.query.myname ;
console.log(username)
res.end(`Hii, ${username}`);
break;
case "/search":
const search = myUrl.query.search_query;
console.log(search)
res.end("Here are your result for "+search);
break;
case '/signup':
if(req.method == 'GET') res.end("This is a signup From");
else if(req.method == "POST"){
//DB Query
res.end("Success");
}
break;
default:
res.end("404 Not Found")
}
})
// console.log(req.headers)
// console.log(req)
});
const PORT = 8000;
myServer.listen(8000, ()=>{
console.log(`Server started at port no ${PORT} `);
})
const express = require("express")
const app = express();
app.get('/',(req , res)=>{
return res.send("Hello from Home Page")
});
app.get('/about' , (req , res)=>{
return res.send(`Hello ${req.query.name}`)
})
const PORT = 8000;
app.listen(8000, ()=>{
console.log(`Server started at port no ${PORT} `);
})
4.18.2
1st Part -> 4 2nd Part -> 18 3rd Part -> 2
3rd part(Last Part) - Miner Fixes (Optional) Latest -> 4.18.3
2nd Part - Recommended Bug Fix (Security) Latest -> 4.19.1
3rd Part -> Major Realese -> Major / Breaking Update Latest -> 5.0.1
"express": "^4.18.3"
^4.18.3 | ^4.18.3 -> 5.0.0
^4.17.9 ^4.18.1 ^4.18.2 ^4.18.3 .. ^5.1.1 β
~4.18.1 ~4.18.2 ~4.18.3 ~4.18.4
~4.19.1 β
- Works on server client architecture.
-
Always Respect All Http methods. Get , Post , Put , Delete
Get /user - user data read kro and return kro
Post /user - handle new user creation
Pathch /user - Update the user
GET /users - HTML Document render - Done GET /api/users - List all users - Done
GET /api/users/1 - Get the user with ID 1 - Done GET /api/users/2 - Get the user with ID 2 - Done
Dynamic Path Parameter GET /api/user/:id :id -> Variable | Dynamic - Done
POST /api/users - Create new user
PATCH /api/users/1 - Edit the user with ID 1
DELETE /api/users/1 - Delete the user with ID 1
const express = require("express");
const users = require("./MOCK_DATA.json")
const app = express();
const PORT = 8000;
//Routes
app.get('/users', (req, res)=>{
const html = `
<ul>
${users.map(user => `<li>${user.first_name}</li>`).join("")}
<ul>
`
res.send(html)
})
//REST Api
app.get('/api/users', (req, res)=>{
return res.json(users);
})
app.route('/api/users/:id').get((req, res)=>{
const id = Number(req.params.id);
const user = users.find(user => user.id === id);
return res.json(user);
})
.patch((req, res) =>{
// TODO : edit the user with id
return res.json({status : 'Pending'})
})
.delete((req , res)=>{
// TODO : delete the user with id
res.json({status : 'Pending'})
})
// app.post('/api/users' , (req , res)=>{
// // TODO : Create new user
// return res.json({status: "pending"});
// })
// app.patch('/api/users/:id' , (req , res)=>{
// // TODO : Edit the user with id
// return res.json({status: "pending"});
// })
// app.delete('/api/users/:id' , (req , res)=>{
// // TODO : delete the user with id
// return res.json({status: "pending"});
// })
app.listen(PORT , ()=>{
console.log(`Server started at Port ${PORT}`)
})
const express = require("express");
const users = require("./MOCK_DATA.json")
const fs = require("fs")
const app = express();
const PORT = 8000;
//Middleware - Plugin
app.use(express.urlencoded({extended:false}));
//Routes
app.get('/users', (req, res)=>{
const html = `
<ul>
${users.map(user => `<li>${user.first_name}</li>`).join("")}
<ul>
`
res.send(html)
})
//REST Api
app.get('/api/users', (req, res)=>{
return res.json(users);
})
app.route('/api/users/:id').get((req, res)=>{
const id = Number(req.params.id);
const user = users.find(user => user.id === id);
return res.json(user);
})
.patch((req, res) =>{
// TODO : edit the user with id
return res.json({status : 'Pending'})
})
.delete((req , res)=>{
// TODO : delete the user with id
res.json({status : 'Pending'})
})
app.post('/api/users' , (req , res)=>{
// TODO : Create new user
const body = req.body;
users.push({...body , id:users.length+1});
fs.writeFile('./MOCK_DATA.json', JSON.stringify(users), (err , data)=>{
return res.json({status:"pending"});
})
console.log(body);
return res.json({status: "sucess", id:users.length});
});
// app.patch('/api/users/:id' , (req , res)=>{
// // TODO : Edit the user with id
// return res.json({status: "pending"});
// })
// app.delete('/api/users/:id' , (req , res)=>{
// // TODO : delete the user with id
// return res.json({status: "pending"});
// })
app.listen(PORT , ()=>{
console.log(`Server started at Port ${PORT}`)
})
Middleware
functions are functions that have access to the request object(req) , the response object(res), and the next middleware function in the application's requests-response cycle.
The next middleware function commanly denoted by variable next
.
- Execute any code.
- Make changes to the request and the response objects.
- End the request-response cycle.
- Call the next middleware function in the stack.
If the current middleware is not functioning then it must call next middle ware otherwise request will be left hanging.
const express = require("express");
const users = require("./MOCK_DATA.json")
const fs = require("fs");
const path = require("path");
const app = express();
const PORT = 8000;
//Middlewares
app.use(express.urlencoded({extended:false}));
app.use((req , res , next) =>{
console.log("Hello from middleware 1");
// return res.json({msg:"Hello from middleware 1"});
req.myUserName= "ayush.dev";
fs.appendFile('log.txt', `${Date.now()} : ${req.ip} ${req.method} : ${req.path} \n` ,(err , data)=>{
next();
})
})
app.use((req , res , next)=>{
console.log("Hello from middleware 2" , req.myUserName);
//return statement stops the execution
// return res.end("Hey");
next();
});
//Routes
app.get('/users', (req, res)=>{
const html = `
<ul>
${users.map(user => `<li>${user.first_name}</li>`).join("")}
<ul>
`
res.send(html)
})
//REST Api
app.get('/api/users', (req, res)=>{
console.log(" I am in get route ", req.myUserName)
return res.json(users);
})
app.route('/api/users/:id').get((req, res)=>{
const id = Number(req.params.id);
const user = users.find(user => user.id === id);
return res.json(user);
})
.patch((req, res) =>{
// TODO : edit the user with id
return res.json({status : 'Pending'})
})
.delete((req , res)=>{
// TODO : delete the user with id
res.json({status : 'Pending'})
})
app.post('/api/users' , (req , res)=>{
// TODO : Create new user
const body = req.body;
users.push({...body , id:users.length+1});
fs.writeFile('./MOCK_DATA.json', JSON.stringify(users), (err , data)=>{
return res.json({status:"pending"});
})
console.log(body);
return res.json({status: "sucess", id:users.length});
});
app.listen(PORT , ()=>{
console.log(`Server started at Port ${PORT}`)
})
An HTTP header is a feild of an HTTP request or response that passes additional contex and metadata about the request or respose.
const express = require("express");
const users = require("./MOCK_DATA.json")
const fs = require("fs");
const path = require("path");
const app = express();
const PORT = 8000;
//Middlewares
app.use(express.urlencoded({extended:false}));
//Routes
app.get('/users', (req, res)=>{
const html = `
<ul>
${users.map(user => `<li>${user.first_name}</li>`).join("")}
<ul>
`
res.send(html)
})
//REST Api
app.get('/api/users', (req, res)=>{
// res.setHeader("myName", "Ayush Kumar");
res.setHeader("X-MyName", "Ayush Kumar"); //Custom header
//Always add X to custum headers
console.log(req.headers)
return res.json(users);
})
app.route('/api/users/:id').get((req, res)=>{
const id = Number(req.params.id);
const user = users.find(user => user.id === id);
return res.json(user);
})
.patch((req, res) =>{
// TODO : edit the user with id
return res.json({status : 'Pending'})
})
.delete((req , res)=>{
// TODO : delete the user with id
res.json({status : 'Pending'})
})
app.post('/api/users' , (req , res)=>{
// TODO : Create new user
const body = req.body;
users.push({...body , id:users.length+1});
fs.writeFile('./MOCK_DATA.json', JSON.stringify(users), (err , data)=>{
return res.json({status:"pending"});
})
console.log(body);
return res.json({status: "sucess", id:users.length});
});
app.listen(PORT , ()=>{
console.log(`Server started at Port ${PORT}`)
})
const express = require("express");
const users = require("./MOCK_DATA.json")
const fs = require("fs");
const path = require("path");
const app = express();
const PORT = 8000;
//Middlewares
app.use(express.urlencoded({extended:false}));
//Routes
app.get('/users', (req, res)=>{
const html = `
<ul>
${users.map(user => `<li>${user.first_name}</li>`).join("")}
<ul>
`
res.send(html)
})
//REST Api
app.get('/api/users', (req, res)=>{
console.log(req.headers)
return res.json(users);
})
app.route('/api/users/:id').get((req, res)=>{
const id = Number(req.params.id);
const user = users.find(user => user.id === id);
// 500 server error
// const user = users.find(user => user[0].id === id);
//If user not found - 404
if(!user) return req.status(404).json({error : 'User Not found'});
return res.json(user);
})
app.post('/api/users' , (req , res)=>{
// TODO : Create new user
const body = req.body;
if(!body || !body.first_name || !body.last_name || !body.email || !body.gender || !body.job_title){
return res.status(400).json({msg: 'ALl fields are required'});
}
users.push({...body , id:users.length+1});
fs.writeFile('./MOCK_DATA.json', JSON.stringify(users), (err , data)=>{
return res.json({status:"pending"});
})
//Status code 201
return res.status(201).json({status: "sucess", id:users.length});
});
app.listen(PORT , ()=>{
console.log(`Server started at Port ${PORT}`)
})
No-SQL Document Based Database.
Strong Support for Aggregation Pipes.
Works on BSON format.
Best for Node Applications.
> show dbs
> use <db_name>
> show collections
> db.coll.find()
> db.coll.insert()
- Schema - Define the Structure Schema - Model Using Model we do CRUD Operation
const express = require("express");
const mongoose = require('mongoose');
const app = express();
const PORT = 8000;
//Connection
mongoose.connect('mongodb://127.0.0.1:27017/learning')
.then(()=> console.log("MongoDB Connected"))
.catch((err) => console.log("Mongo Error" , err));
//Schema
const userSchema = new mongoose.Schema({
firstName: {
type: String,
required : true,
},
lastName : {
type: String,
},
email:{
type: String,
required : true,
unique: true,
},
jobTitle: {
type: String,
}
},
{timestamps: true}
)
// Model
const User = mongoose.model('user' , userSchema);
//Middlewares
app.use(express.urlencoded({extended:false}));
//Routes
app.get('/users', async(req, res)=>{
const allDbUsers = await User.find({});
const html = `
<ul>
${allDbUsers.map(user => `<li>${user.firstName} - ${user.email}</li>`).join("")}
<ul>
`
res.send(html)
})
//REST Api
app.get('/api/users', async(req, res)=>{
const allDbUsers = await User .find({});
return res.json(allDbUsers);
})
app.
route('/api/users/:id')
.get( async(req, res)=>{
const user = await User.findById(req.params.id)
if(!user) return req.status(404).json({error : 'User Not found'});
return res.json(user);
})
.patch(async (req,res) =>{
await User.findByIdAndUpdate(req.params.id ,{ lastName:"Changed" } );
return res.json({status : "Success"});
})
.delete( async(req , res) => {
await User.findByIdAndDelete(req.params.id);
return res.json({status : "Success"});
})
app.post('/api/users' , async(req , res)=>{
// TODO : Create new user
const body = req.body;
if(!body || !body.first_name || !body.last_name || !body.email || !body.gender || !body.job_title){
return res.status(400).json({msg: 'ALl fields are required'});
}
const result = await User.create({
firstName : body.first_name,
lastName : body.last_name,
email: body.email,
gender : body.gender,
jobTitle: body.job_title
});
console.log("result" , result);
return res.status(201).json({msg: "Success"})
});
app.listen(PORT , ()=>{
console.log(`Server started at Port ${PORT}`)
})
Model View Controller
------------------------
Model
/ \
/ \
View Contoller
-
Statefull - Which maintains state or data on server side
-
Stateless - Which has no state.
In statefull authentication server works as a parking boy which stores the car no. with a unique mapped no.
Server gives the mapped number gives to the user as a parking ticket .
When user visit again to take the car the parking boy (server) maps the data , the user is authentic or not . If yes then server gives the permission to user to take the car.(maintain a state)
Server can transfer the unique id using cookies, respose , headers to the cilent.
=> If server restart or some reason server lost , all users get logged out.
=> Memory intensive
=> No states => We use JWT(JSON Web Tokens) Tokens => Maintain the state on local browser using encoded msg of payload(token) and secret key. => Secret should be secret.
Server make the token.
Server can the send the token to the user through Cookies
and Response
.
Browser stores the cookies.
We can use the cookie to validate the user.
The server makes the cookies for the domain to which those cookies belong.(Cookies are domain specific.)
We can specify domain to the cookie.Which domain can acess that cookie.
We can also specify the expiration of the cookie.
res.cookie("uid", token , {
domain : "ayushk.dev" // ayushk.dev can access
domain : ".ayushk.dev" // blog.ayushk.dev can access
//app.ayushk.dev also can access
})
It is only limited to the browser.
Bearer authentication is also called as token authentication.
It is an HTTP auth
.
Header{
Authorization : Bearer <token>
}
Server reads the header and removes the bearer and takes the token to validate the user.
Authorization is the process of giving someone the ability to access a resource.
- installed EJS , Express and Multer Packages
- Created a Form in ejs
- Added action="folder" , method+"post" and erictype="multipart/form-data" in form
- A form can have data + files so must use enctype.
- Use middileware `express.urlencoded({}) which helps to parse the form data.
- Using disk storage to get full control on files.
- We can store
req.file.path
to the database to get the files easily. - We use
upload.single
to upload single image. - We can use
upload.array
andupload.fields
to upload multiple files.
--dev
use to make Development dependency.- Dev dependency is required only in development enviornment.
- Ex:
npm i nodemon --dev
- It will not be used in Production enviornment.
- We haave used
Partials
Folder Which includes all the files which are partial for many other files. - Steps :
- Created Models
- Created Views
- Created Router to handle request
- Hashed the password using crypto library
- Worked on Signup page
- Worked on Signin page
- Signup and signin done
--dev
use to make Development dependency.- Dev dependency is required only in development enviornment.
- Ex:
npm i nodemon --dev
- It will not be used in Production enviornment.
- We haave used
Partials
Folder Which includes all the files which are partial for many other files. - Steps :
- Created Models
- Created Views
- Created Router to handle request
- Hashed the password using crypto library
- Worked on Signup page
- Worked on Signin page
- Signup and signin done
- Created a JWT Token
- Creation and valiation of JWT token
- made payload for valid user
- Saved in localstorage
- Created a middleware to check for authentication cookie
- Installed
cookie-parser
library and used it - Made a route for clear cookie(logout)
- set the token with full name and displayed the full name at username by me
- created blog schema and model
- Made Blog Router And Schema
- Created a blog page
- Stored the blog in database
- Used multer to store the image
- Used
express.static(path.resolve('./public')
middleware to get access to static files(blog image)
--dev
use to make Development dependency.- Dev dependency is required only in development enviornment.
- Ex:
npm i nodemon --dev
- It will not be used in Production enviornment.
- We haave used
Partials
Folder Which includes all the files which are partial for many other files. - Steps :
- Created Models
- Created Views
- Created Router to handle request
- Hashed the password using crypto library
- Worked on Signup page
- Worked on Signin page
- Signup and signin done
- Created a JWT Token
- Creation and valiation of JWT token
- made payload for valid user
- Saved in localstorage
- Created a middleware to check for authentication cookie
- Installed
cookie-parser
library and used it - Made a route for clear cookie(logout)
- set the token with full name and displayed the full name at username by me
- created blog schema and model
- Made Blog Router And Schema
- Created a blog page
- Stored the blog in database
- Used multer to store the image
- Used
express.static(path.resolve('./public')
middleware to get access to static files(blog image)
- We can't set
PORT
for App on the server by own. - We need a enviournment variable i.e. Dynamic Variable.
- Enviornment variable is set by cloud.
process.env.Variable_Name
- For cloud sever make sure you have start script
"start": "node app.js"
- For Node.js, the main file is typically app.js
-
In general , We send request to the server , server responds to our request and request-response cycle will be closed.
-
Communication is single direction. Client request then Server responds (req-res cycle closed)
-
Problem :
- Everytime when user request to the server there is message is available or not. (Chat App)
- This is called
Polling
. - If message is not available then we are also reuesting to the server
- Unneccesarly increasing the load to the server.
-
Solution :
- Clinet sent
HTTP
request and tells , i want to makeWebSocket
connection. Upgrade
Header upgradeshttp
connection towebsocket
connection.- any one can send message (server <--> Client) (Bidirectional).
- You don't close the websocket connection unless you want.
- WebSocket is just a
protocol
, providesfull-duplex
communication. - We don't need
Polling
.
- Clinet sent
-
We use
Socket.io
Library.
- Multiple users concurrently accesing the server then Workload increases.
- When users increases then we can use clusters.
- We distribute the workload on server into multiple apllication threads of nodejs.
- We can make worker threads as no of cpus.
- When we use cluster it divides assigns the diifferent work with diffirent threads in nodejs in round robin fashion to distribute the workload.
-
NGINX is a powerful web server and uses a non-threaded , event-driven architecture.
-
It can also do other important things ,such as
load balancing
, andHTTP caching
, or be used as areverse proxy
. -
Forward Proxy
- When multiple clients connecting to VPN Sever. And VPN sever is connecting to a server.
- Only one client for server i.e. VPN.
-
Reverse Proxy:
- When a clinet is connecting a VPN server and that vpn is connecting to multiple servers.
- Users don't know request will be serve to which server.
-
Reverse Proxy:
- Nginx decides your request will be serve to which server.
-
Load Balance - distribute the load.
-
Http Cache - make cache to reduce req-res cycle.
-
Advantage:
- Can handle 10000 concurrent requests
- Cache HTTP requests
- Act as Reverse Proxy
- Act as Load Balancer
- Act as an API Gateway
- Serve and Cache Static files like images, Videos, etc
- Handle SSL Certificates
-
Prerequisite
- Docker , Basic Linux Commands , Containerization
- It is Query Language to make api calls.
- Gives clients the power to ask for exactly what they need and nothing more.
-
When we make an api call it servers all the data of the particular id from database.
-
We use the required data and ignore the others data that we don't want to use or show.
-
The problem is every time we call api then it serves all the data which is not required.
-
To get the only required data from the database we use GraphQL, It serve the only neccessary that user wants.(reduce over-fetching of data)
-
!
used to define required field.
-
A Javscript library used for making HTTP requests from web browsers and Node.js applications.
-
Features : request and response interception, automatic transformation of JSON data, and the ability to cancel requests.
-
Code :
-
const server = new ApolloServer({ typeDefs: ` type User { id: ID! name: String! username: String! email: String! phone: String! website: String! } type Todo { id: ID! title : String! completed: Boolean user: User }, type Query { getTodos: [Todo] getAllUsers: [User] getUser(id: ID!): User } `, resolvers: { Todo: { user: async(todo) => (await axios.get(`https://jsonplaceholder.typicode.com/users/${todo.userId}`)).data }, Query: { getTodos: async () =>{ return (await axios.get("https://jsonplaceholder.typicode.com/todos")).data; }, getAllUsers: async () => { return (await axios.get("https://jsonplaceholder.typicode.com/users")).data; }, getUser: async (_, { id }) => { return (await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`)).data; }, }, }, });
-