Node.js Quick Reference
A quick lookup for Node.js and Express patterns grouped by category. All examples use TypeScript.
Core Modules
Section titled “Core Modules”fs (File System)
Section titled “fs (File System)”import fs from 'fs'
// Synchronousconst 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-basedimport { 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.tspath.resolve('src', 'index.ts') // absolute pathpath.dirname('/src/routes/users.ts') // /src/routespath.basename('/src/routes/users.ts') // users.tspath.extname('users.ts') // .tsprocess
Section titled “process”process.env.PORT // environment variableprocess.argv // command-line argumentsprocess.cwd() // current working directoryprocess.exit(1) // exit with error codeExpress
Section titled “Express”Server setup
Section titled “Server setup”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'))Routes
Section titled “Routes”// HTTP methodsapp.get('/posts', handler)app.post('/posts', handler)app.put('/posts/:id', handler)app.patch('/posts/:id', handler)app.delete('/posts/:id', handler)
// Route paramsapp.get('/posts/:id', (req, res) => { const id = Number(req.params.id)})
// Query strings — GET /posts?page=2&limit=10app.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})Responses
Section titled “Responses”res.json({ id: 1, title: 'Hello' }) // 200 JSONres.status(201).json({ id: 1 }) // 201 Createdres.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' })Router
Section titled “Router”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.tsimport postRoutes from './routes/posts'app.use('/posts', postRoutes)Error-handling middleware
Section titled “Error-handling middleware”// Must have 4 parameters — Express identifies it as error handlerapp.use((err: Error, req: Request, res: Response, next: NextFunction) => { console.error(err.stack) res.status(500).json({ error: 'Internal server error' })})SQLite (better-sqlite3)
Section titled “SQLite (better-sqlite3)”import Database from 'better-sqlite3'
const db = new Database('app.db')
// Create tabledb.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 objectconst stmt = db.prepare('INSERT INTO posts (title, body, userId) VALUES (?, ?, ?)')const result = stmt.run(title, body, userId)result.lastInsertRowid // new row's ID
// Select oneconst post = db.prepare('SELECT * FROM posts WHERE id = ?').get(id)
// Select manyconst posts = db.prepare('SELECT * FROM posts ORDER BY createdAt DESC').all()
// Updatedb.prepare('UPDATE posts SET title = ? WHERE id = ?').run(title, id)
// Deletedb.prepare('DELETE FROM posts WHERE id = ?').run(id)
// Transactionconst 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)Authentication
Section titled “Authentication”bcrypt
Section titled “bcrypt”import bcrypt from 'bcrypt'
const SALT_ROUNDS = 10
// Hash a passwordconst hash = await bcrypt.hash(plainPassword, SALT_ROUNDS)
// Verify a passwordconst match = await bcrypt.compare(plainPassword, hash)// match === true → correct; false → wrongimport jwt from 'jsonwebtoken'
const SECRET = process.env.JWT_SECRET!
// Sign a tokenconst token = jwt.sign( { userId: user.id, username: user.username }, SECRET, { expiresIn: '24h' })
// Verify a tokentry { const payload = jwt.verify(token, SECRET) as { userId: number; username: string }} catch { // invalid or expired}Auth middleware
Section titled “Auth middleware”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' }) }}Environment Variables
Section titled “Environment Variables”PORT=3000JWT_SECRET=supersecretDATABASE_URL=./app.dbimport 'dotenv/config'
const port = process.env.PORT ?? '3000'const secret = process.env.JWT_SECRET! // ! asserts non-nullNever commit .env files. Add them to .gitignore.
Rate Limiting
Section titled “Rate Limiting”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 endpointsconst authLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 10 })app.use('/users/login', authLimiter)app.use('/users/register', authLimiter)TypeScript setup (tsx / tsc)
Section titled “TypeScript setup (tsx / tsc)”{ "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" }}Common HTTP Status Codes
Section titled “Common HTTP Status Codes”| Code | Name | When to use |
|---|---|---|
| 200 | OK | Successful GET or PUT |
| 201 | Created | Successful POST that creates a resource |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Missing or invalid input |
| 401 | Unauthorized | No token or invalid token |
| 403 | Forbidden | Valid token but insufficient permissions |
| 404 | Not Found | Resource doesn’t exist |
| 409 | Conflict | Duplicate resource (e.g., username taken) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Unhandled server-side error |
REST API Naming Conventions
Section titled “REST API Naming Conventions”| Action | Method | Path |
|---|---|---|
| List all | GET | /posts |
| Get one | GET | /posts/:id |
| Create | POST | /posts |
| Replace | PUT | /posts/:id |
| Partial update | PATCH | /posts/:id |
| Delete | DELETE | /posts/:id |
| Nested resource | POST | /posts/:id/comments |
| Action | POST | /posts/:id/upvote |