Skip to content

Node.js Quick Reference

A quick lookup for Node.js and Express patterns grouped by category. All examples use TypeScript.

import fs from 'fs'
// Synchronous
const content = fs.readFileSync('file.txt', 'utf-8')
fs.writeFileSync('file.txt', 'hello')
// Async (callback)
fs.readFile('file.txt', 'utf-8', (err, data) => {
if (err) throw err
console.log(data)
})
// Promise-based
import { readFile, writeFile } from 'fs/promises'
const data = await readFile('file.txt', 'utf-8')
await writeFile('file.txt', 'hello')
import path from 'path'
path.join('src', 'routes', 'users.ts') // src/routes/users.ts
path.resolve('src', 'index.ts') // absolute path
path.dirname('/src/routes/users.ts') // /src/routes
path.basename('/src/routes/users.ts') // users.ts
path.extname('users.ts') // .ts
process.env.PORT // environment variable
process.argv // command-line arguments
process.cwd() // current working directory
process.exit(1) // exit with error code

import express from 'express'
import cors from 'cors'
import helmet from 'helmet'
const app = express()
app.use(helmet())
app.use(cors({ origin: 'http://localhost:5173' }))
app.use(express.json())
app.listen(3000, () => console.log('Server running on port 3000'))
// HTTP methods
app.get('/posts', handler)
app.post('/posts', handler)
app.put('/posts/:id', handler)
app.patch('/posts/:id', handler)
app.delete('/posts/:id', handler)
// Route params
app.get('/posts/:id', (req, res) => {
const id = Number(req.params.id)
})
// Query strings — GET /posts?page=2&limit=10
app.get('/posts', (req, res) => {
const { page = '1', limit = '10' } = req.query
})
// Request body (requires express.json() middleware)
app.post('/posts', (req, res) => {
const { title, body } = req.body
})
res.json({ id: 1, title: 'Hello' }) // 200 JSON
res.status(201).json({ id: 1 }) // 201 Created
res.status(400).json({ error: 'Bad request' })
res.status(401).json({ error: 'Unauthorized' })
res.status(403).json({ error: 'Forbidden' })
res.status(404).json({ error: 'Not found' })
res.status(204).send() // No content (DELETE)
res.status(500).json({ error: 'Internal server error' })
src/routes/posts.ts
import { Router } from 'express'
const router = Router()
router.get('/', getPosts)
router.get('/:id', getPost)
router.post('/', authenticate, createPost)
router.delete('/:id', authenticate, deletePost)
export default router
// src/index.ts
import postRoutes from './routes/posts'
app.use('/posts', postRoutes)
// Must have 4 parameters — Express identifies it as error handler
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error(err.stack)
res.status(500).json({ error: 'Internal server error' })
})

import Database from 'better-sqlite3'
const db = new Database('app.db')
// Create table
db.exec(`
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
body TEXT NOT NULL,
userId INTEGER NOT NULL,
createdAt TEXT DEFAULT (datetime('now'))
)
`)
// Insert — returns info object
const stmt = db.prepare('INSERT INTO posts (title, body, userId) VALUES (?, ?, ?)')
const result = stmt.run(title, body, userId)
result.lastInsertRowid // new row's ID
// Select one
const post = db.prepare('SELECT * FROM posts WHERE id = ?').get(id)
// Select many
const posts = db.prepare('SELECT * FROM posts ORDER BY createdAt DESC').all()
// Update
db.prepare('UPDATE posts SET title = ? WHERE id = ?').run(title, id)
// Delete
db.prepare('DELETE FROM posts WHERE id = ?').run(id)
// Transaction
const transfer = db.transaction((from: number, to: number, amount: number) => {
db.prepare('UPDATE accounts SET balance = balance - ? WHERE id = ?').run(amount, from)
db.prepare('UPDATE accounts SET balance = balance + ? WHERE id = ?').run(amount, to)
})
transfer(1, 2, 100)

import bcrypt from 'bcrypt'
const SALT_ROUNDS = 10
// Hash a password
const hash = await bcrypt.hash(plainPassword, SALT_ROUNDS)
// Verify a password
const match = await bcrypt.compare(plainPassword, hash)
// match === true → correct; false → wrong
import jwt from 'jsonwebtoken'
const SECRET = process.env.JWT_SECRET!
// Sign a token
const token = jwt.sign(
{ userId: user.id, username: user.username },
SECRET,
{ expiresIn: '24h' }
)
// Verify a token
try {
const payload = jwt.verify(token, SECRET) as { userId: number; username: string }
} catch {
// invalid or expired
}
import { Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken'
export function authenticate(req: Request, res: Response, next: NextFunction) {
const authHeader = req.headers.authorization
const token = authHeader?.split(' ')[1] // "Bearer <token>"
if (!token) {
res.status(401).json({ error: 'No token provided' })
return
}
try {
const payload = jwt.verify(token, process.env.JWT_SECRET!) as JwtPayload
req.user = payload
next()
} catch {
res.status(401).json({ error: 'Invalid or expired token' })
}
}

.env
PORT=3000
JWT_SECRET=supersecret
DATABASE_URL=./app.db
import 'dotenv/config'
const port = process.env.PORT ?? '3000'
const secret = process.env.JWT_SECRET! // ! asserts non-null

Never commit .env files. Add them to .gitignore.


import rateLimit from 'express-rate-limit'
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max requests per window
message: { error: 'Too many requests' },
})
app.use(limiter)
// Stricter limit for auth endpoints
const authLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 10 })
app.use('/users/login', authLimiter)
app.use('/users/register', authLimiter)

tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "dist",
"strict": true,
"esModuleInterop": true
},
"include": ["src"]
}
// package.json scripts
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
}

CodeNameWhen to use
200OKSuccessful GET or PUT
201CreatedSuccessful POST that creates a resource
204No ContentSuccessful DELETE
400Bad RequestMissing or invalid input
401UnauthorizedNo token or invalid token
403ForbiddenValid token but insufficient permissions
404Not FoundResource doesn’t exist
409ConflictDuplicate resource (e.g., username taken)
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnhandled server-side error

ActionMethodPath
List allGET/posts
Get oneGET/posts/:id
CreatePOST/posts
ReplacePUT/posts/:id
Partial updatePATCH/posts/:id
DeleteDELETE/posts/:id
Nested resourcePOST/posts/:id/comments
ActionPOST/posts/:id/upvote