Skip to content

Latest commit

 

History

History
85 lines (68 loc) · 6.85 KB

node-express-ts.md

File metadata and controls

85 lines (68 loc) · 6.85 KB

File Structure and Organization

  • All route handlers must live in src/routes/ with one file per logical domain (e.g., src/routes/users.ts, src/routes/products.ts). Never put routes in index.ts.
  • All business logic must live in src/services/ with one file per domain (e.g., src/services/UserService.ts). Services are classes with static methods or instance methods, never functions.
  • All database queries must live in src/repositories/ with one file per entity (e.g., src/repositories/UserRepository.ts). Repositories are classes, never raw query functions.
  • All middleware must live in src/middleware/ with descriptive names (e.g., src/middleware/authMiddleware.ts, src/middleware/validationMiddleware.ts).
  • All custom error classes must live in src/errors/ with one file per error type (e.g., src/errors/ValidationError.ts, src/errors/NotFoundError.ts).
  • All type definitions must live in src/types/ with one file per domain (e.g., src/types/user.ts, src/types/product.ts). Never inline interfaces in route files.
  • All validators must live in src/validators/ using Zod schemas (e.g., src/validators/userValidator.ts). One schema per entity.
  • All tests must live in src/__tests__/ mirroring the source structure (e.g., src/__tests__/services/UserService.test.ts).
  • src/index.ts must only import and wire together middleware, routes, and error handlers. Maximum 50 lines.

Code Style and Naming

  • Use const exclusively. Never use let or var.
  • All function names must be camelCase. All class names must be PascalCase. All constants must be UPPER_SNAKE_CASE.
  • All exported functions and classes must have explicit return type annotations. Never use implicit any returns.
  • File names must be camelCase for utilities and middleware (e.g., authMiddleware.ts), PascalCase for classes (e.g., UserService.ts).
  • All imports must use absolute paths from src/ (e.g., import { UserService } from 'src/services/UserService'). Never use relative paths like ../../../.
  • Use export const for named exports only. Never use export default.
  • All object properties in types must use explicit types, never any. Use unknown if truly unknown, then narrow with type guards.

Type Safety and TypeScript

  • Never use as type assertions outside of test files. Use type guards or Zod .parse() instead.
  • All function parameters must have explicit types. No implicit any.
  • All Express route handlers must have explicit types: (req: Request, res: Response, next: NextFunction): void => { }. Never omit next.
  • All req.body access must be preceded by validation using Zod. Never trust req.body directly.
  • All req.params and req.query must be validated with Zod before use.
  • All database query results must be validated against their expected type using Zod or explicit type guards.
  • Never use Object, object, or {} as types. Use Record<string, unknown> or specific interfaces.

Error Handling

  • All custom errors must extend Error and include a statusCode property (e.g., class ValidationError extends Error { statusCode = 400; }).
  • All async functions must have try/catch blocks. Caught errors must be typed: catch (err) { if (err instanceof AppError) { ... } else { throw new UnexpectedError(); } }.
  • All route handlers must call next(err) when catching errors, never res.status().json() directly in catch blocks.
  • Error middleware must be the last middleware registered in src/index.ts. It must catch all errors and return a structured response with { error: string; statusCode: number; } — never raw error messages.
  • Never return error.message directly to the client. Map errors to user-safe messages in the error middleware.
  • All errors returned to the client must have a statusCode between 400-599. Never return 200 with an error.
  • Validation errors must return 400 with a { error: string; details: Record<string, string[]>; } structure from Zod .safeParse().

Request Validation

  • All POST/PUT/PATCH handlers must validate req.body using a Zod schema before accessing any property.
  • All GET handlers with query parameters must validate req.query using a Zod schema.
  • All route parameters (:id, :slug) must be validated with Zod before passing to services.
  • Validation must happen in middleware or at the start of the route handler, never deep in business logic.
  • Zod schemas must be defined in src/validators/ and imported, never inline in route files.

Security

  • Never hardcode secrets, API keys, or database credentials. All must come from environment variables via process.env.
  • All environment variables must be validated at startup using Zod in src/config/env.ts. The app must crash if required vars are missing.
  • Never log req.body, req.headers, or req.query directly. Sanitize sensitive fields before logging.
  • All user input must be trimmed and validated for length before storage: Zod.string().trim().max(255).
  • Never use eval(), Function(), or dynamic require() with user input.
  • All database queries must use parameterized queries or ORM methods, never string concatenation.
  • CORS must be explicitly configured in src/middleware/corsMiddleware.ts with a whitelist, never *.

Testing

  • All services must have unit tests in src/__tests__/services/ with .test.ts extension.
  • All route handlers must have integration tests in src/__tests__/routes/ with .test.ts extension.
  • All tests must use Jest with describe() and it() blocks. Never use test().
  • All async tests must use async/await, never .then() chains.
  • All mocked dependencies must be imported with jest.mock() at the top of the test file.
  • All tests must clean up database state in afterEach() hooks.
  • Error cases must be tested explicitly: test that invalid input returns 400, that missing auth returns 401, etc.
  • Test files must have at least 80% coverage of the service or route they test.

Express-Specific Patterns

  • All route files must export a single function: export const setupUserRoutes = (app: Express): void => { }.
  • All middleware must be typed: (req: Request, res: Response, next: NextFunction): void => { } or (err: Error, req: Request, res: Response, next: NextFunction): void => { } for error middleware.
  • All route handlers must be async functions that call next(err) on error, never res.status().json() in catch blocks.
  • All responses must use res.status(code).json(data), never res.send() or res.end().
  • All successful responses must return { data: T; } or { data: T[]; } structure, never raw objects.
  • All 404 responses must be handled by a catch-all route at the end of src/index.ts that returns { error: 'Not Found'; statusCode: 404; }.

Source: Codelibrium — the marketplace for AI behaviour files. Browse multiple rulesets at codelibrium.com or install via CLI: npx codelibrium-cli install <ruleset-name>