For full hot+flash+database_connected please refer to testing-hot-flash
directory in this repo.
- (Failue attempt to help share common files b/w frontend and backend) Svelte + Expressjs: sahilrajput03/svelte-express
Please keep below text for future references of offline repos to be trackable back to this repo.
- Added
async-config-in-servers
mini-setup done with Lalit @blulabs - Added
test-quokkajs-with-express
repo. - Added
expressReqBodyWithTypeGuarding
repo. - Added
express-testing-middlwares-with-nextCalls
repo. - Added
cookies-and-requests-with-express
- Added
react-express
repo. - Added
jwt-secure-authorization
repo. - Added
nodejs-development-in-docker-container
repo. - Added
node-hot-api-testing
repo. - Added
node-modules-concept
repo. - Added
learning_javascript_nodejs
repo. - Added
custom-NODE_PATH
repo. - Added
ecma-wonder-in-node
repo. - Added
learn-assertions
repo.
Quick Links:
- Learn limiting concurrent requests with
queue()
ofasync
library (awesome): Click here
- My Expressjs + Typescript Example Project:
ts-node-dev
example: ⭐Click here⭐- Check readme in above folder to see instructions for creating from scratch.
- Article: Dev.to Article: Click here - Github Repo
// NOTE: I tested using `ts-node-dev --respawn --transpile-only --clear --dotenv src/app.ts` but I get following error in a recent qr-project:
ts-node-dev: no script to run provided
// Result: I am using `dotenv` again. LOL
Starting with Node.js v20.6.0, the ability to load .env files into the process.env object using the built-in dotenv loader was introduced.
node --dotenv index.js
# you can specify a custom .env file path by setting the NODE_ENV_FILE environment variable before running your application. Here's how you can do it:
NODE_ENV_FILE=./config/custom.env node --dotenv index.js
import cookieParser from 'cookie-parser'
app.use(cookieParser()); // Use cookie-parser middleware
app.get('/u1', async (req: Request, res: Response) => {
res.cookie('name', 'Sahil Rajput', { maxAge: 900000 }); // "maxAge": Lifetime of the cookie in milliseconds
res.redirect('/get-cookie');
})
app.get('/get-cookie', async (req: Request, res: Response) => {
const name = req.cookies.name;
if (name) {
res.send(`Hello, ${name}`);
} else {
res.send('No name cookie found. Go back to to <a href="/u1">/u1</a>');
}
})
// From abhinav
// console.log('req.headers.origin?', req?.headers.origin)
// OUTPUT: https://staging-bscl.lucify.in
const pdomain = req?.headers.origin?.split('.').splice(1, 2).join('.')
// OUTPUT: lucify.in (for request from frontned having url: https://staging-bscl.lucify.in/
const domain = isProduction ? pdomain : 'localhost'
// const domain = isProduction ? '.lucify.in' : 'localhost'
// TESTED: Below code works:
// backend: https://bscl-staging-backend.onrender.com/
// frontend: https://staging-bscl.lucify.in/
const expires = new Date(Date.now() + cookieExpireValue * 24 * 60 * 60 * 1000)
const cookieConfig: CookieOptions = {
expires,
secure: !!isProduction,
sameSite: isProduction ? 'none' : false,
// TODO: In future, we might want to use below fields for production when we have backend and frontend on same top level domain i.e., lucify.in:
// httpOnly: true,
// domain
}
return res
.status(statusCode)
.cookie('token', token, cookieConfig)
.json({
success: true,
user,
token,
})
}
Other suggestions from chatgpt for setting domain
property:
way1
OR way2:
- MDN Docs: Click here
express-async-handler
- Github: express-async-handler
- Npm: Click here
Source - Click here
node --expose-gc
process.memoryUsage();
// or may be can do Import process from 'node/process???'
Get my guide and links by clicking here.
export declare enum HttpStatus {
CONTINUE = 100,
SWITCHING_PROTOCOLS = 101,
PROCESSING = 102,
EARLYHINTS = 103,
OK = 200,
CREATED = 201,
ACCEPTED = 202,
NON_AUTHORITATIVE_INFORMATION = 203,
NO_CONTENT = 204,
RESET_CONTENT = 205,
PARTIAL_CONTENT = 206,
AMBIGUOUS = 300,
MOVED_PERMANENTLY = 301,
FOUND = 302,
SEE_OTHER = 303,
NOT_MODIFIED = 304,
TEMPORARY_REDIRECT = 307,
PERMANENT_REDIRECT = 308,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
PAYMENT_REQUIRED = 402,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
NOT_ACCEPTABLE = 406,
PROXY_AUTHENTICATION_REQUIRED = 407,
REQUEST_TIMEOUT = 408,
CONFLICT = 409,
GONE = 410,
LENGTH_REQUIRED = 411,
PRECONDITION_FAILED = 412,
PAYLOAD_TOO_LARGE = 413,
URI_TOO_LONG = 414,
UNSUPPORTED_MEDIA_TYPE = 415,
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
EXPECTATION_FAILED = 417,
I_AM_A_TEAPOT = 418,
MISDIRECTED = 421,
UNPROCESSABLE_ENTITY = 422,
FAILED_DEPENDENCY = 424,
PRECONDITION_REQUIRED = 428,
TOO_MANY_REQUESTS = 429,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505
}
Source of Inspiration: https://github.com/axios/axios/blob/main/ECOSYSTEM.md
- Axiosist on npm: http://npm.im/axiosist
- Github/Docs: https://github.com/Gerhut/axiosist
const axios = require('axios')
const axiosist = require('axiosist')
const express = require('express')
const app = express()
app.use(express.json())
app.get('/host', (req, res) => res.send(req.get('host')))
app.get('/name', (req, res) => res.send({name: 'john'}))
app.post('/user', (req, res) => res.send({...req.body}))
const server = axiosist(app) // equivalent to below
// const server = axios.create({adapter: axiosist.createAdapter(app)})
void (async () => {
const response = await server.get('/host')
console.log('got resp.data', response.data)
})()
void (async () => {
const response = await server.get('/name')
console.log('name?', response.data)
})()
// Axiosist will keep the host header of the request, for example
void (async () => {
const response = await server.get('https://loveapi.ml/host')
if (response.data !== 'loveapi.ml') throw new Error('failed.')
})()
void (async () => {
const usr = {name: 'Sahil', age: 10}
const {data} = await server.post('/user', usr)
if (data.name !== usr.name || data.age !== usr.age) throw new Error('user requets failed')
})()
Using sahilrajput03-logger
:
PLEASE READ ITS README: https://github.com/sahilrajput03/logger-npm#readme
Status Codes for http: Click here
PUT vs. PATCH in http requests
The main difference between the PUT and PATCH method is that the PUT method uses the request URI to supply a modified version of the requested resource which replaces the original version of the resource, whereas the PATCH method supplies a set of instructions to modify the resource.
What is the use of express-async-errors
npm package
-
ALERT: You must have error printing
console.log(error)
in any of your middleware to print the db errors else you won't see db errors in your server terminal at all. For exact usage instruction refer projects here. -
FYI: express-async-errors also prevents server crasing if any route throws some error as well(this is really very IMPORTANT in production server that one bad endpoint doesn't cause entire server to go down). I.e.,
So above happend instead of: which is really very important in any production server.
Source: express-async-errors@github, Fullstackopen.com.
Sample server code for code structure reference @ https://www.digitalocean.com/community/tutorials/test-a-node-restful-api-with-mocha-and-chai
- FYI: We can put break point on the end of the function to check the value of last variable in the fuction as well.
FYI: For loading env from a file using command line env-cmd is an amazing tool: https://www.npmjs.com/package/env-cmd
Using morgan specifics:
Learn: What is content-length
anyway?
- src1: It's the number of bytes of data in the body of the request or response. The body is the part that comes after the blank line below the headers.
- src2: The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient.
# custom
# morgan.token('body', (req, res) => JSON.stringify(req.body))
# app.use(morgan(':method :url :status :body - :response-time ms'))
PUT /api/users/jami_kousa 200 {"disabled":false} - 3.916 ms
POST /api/login 200 {"username":"jami_kousa","password":"secret"} - 1.201 ms
# custom (with response content-length)
# morgan.token('body', (req, res) => JSON.stringify(req.body))
# app.use(morgan(':method :url :status :body - :response-time ms - :res[content-length]'))
PUT /api/users/jami_kousa 200 {"disabled":false} - 4.020 ms - 83
POST /api/login 200 {"username":"jami_kousa","password":"secret"} - 1.145 ms - 203
# with app.use(morgan('tiny')) # :method :url :status :res[content-length] - :response-time ms
PUT /api/users/jami_kousa 200 83 - 6.340 ms
POST /api/login 200 203 - 1.934 ms
# with app.use(morgan('short')) # :remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms
::ffff:127.0.0.1 - PUT /api/users/jami_kousa HTTP/1.1 200 83 - 9.335 ms
::ffff:127.0.0.1 - POST /api/login HTTP/1.1 200 203 - 1.736 ms
# with app.use(morgan('combined')) # :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
::ffff:127.0.0.1 - - [26/Jul/2022:07:19:07 +0000] "PUT /api/users/jami_kousa HTTP/1.1" 200 83 "-" "-"
::ffff:127.0.0.1 - - [26/Jul/2022:07:19:07 +0000] "POST /api/login HTTP/1.1" 200 203 "-" "-"
Read here.
Also read the original code of express's res.json
and res.send
code here.
FYI: I created a entry for launch config
in system wide settings.json
file so I don't necessaryily need to add below launch.json
file for each nodejs based project or any file coz I CAN DIRECTLY CALL DEBUGGER NOW!!!!. Yikes!
1. Create a file .vscode/launch.json
in root folder.
{
// Q. What process to attach with this debugger ???
// ANSWER. Select this setting in the debugger dropdown first then press f5 key (or use the green play button) (use shift+f5 to stop debugger anytime later) in vscode and in command pallete entries or processes you need to select the entry with text `nodemon --inspect app.js` or `nodemon --inspect-brk app.js`. ROCKON!
"name": "Attach to nodemon process ~Sahil",
"type": "pwa-node",
"request": "attach",
// ^^ note that this is a of type attach and we have specified to `restart` via the restart option below to reattch to that process and pick the new processid automatically, yikes!
// Get debugger select-dropdown with f5 key (use shift+f5 to stop debugger) in vscode and select the entry with text nodemon --inspect app.js or nodemon --inspect-brk app.js in the list of processes in there. ROCKON!
"processId": "${command:PickProcess}",
"restart": true,
"protocol": "inspector"
// "envFile": "${workspaceFolder}/.env"
// ^^^ This is not required at all when we are using dotenv to load .env file, 1 May, 2022.
// Our .env file is loaded simply (no need of cross-env), also the terminal would pick the values of `.env` file once you attach the debugger. Yikes!
},
2. Now use nodemon to start the server i.e., nodemon --inspect app.js
. (NOTE: .env
file will be in effect once the vscode debugger is attached). FYI: You can use alias like nma file.js
or nmas file.js
for nodemon --inspect
or nodemon --inspect-brk
respectively.**
You can break on the very first line of the program via flag
--inspect-brk
instead of--inspect
in you node/nodemon command. Src, Src2, Src3, Src4 @ FSO. The benefit of using --inspect-brk can ensure that our program must break at the desired breakpoint coz in some cases the oprations in the our app.js gets done even before getting the debugger attached so the breakpoint gets missed thus to ensure that our desired breakpoint must hit we use --inspect-brk thus the program won't even run at all from the very first line of code so our node app gets enough time to get the vscode debugger attached and then we start the program execution. Yikes!
3. Get debugger select-dropdown
with f5
key (use shift+f5
to stop debugger) in vscode and select the entry with text nodemon --inspect app.js
or nodemon --inspect-brk app.js
in the list of processes in there. ROCKON!
IMPORTANT: FYI: Read about the paramters you can use in
configuration
forlaunch
settings in vscode: Click here.
More
-
TIP: Use f9 to add/remove the breakpoint.
-
Loading .env file in the debugging mode. Src
-
Remote debugging applications: @nodejs docs, @vscode docs.