Skip to main content

nodejs-backend

Node.js backend patterns: framework selection, layered architecture, TypeScript, validation, error handling, security, production deployment. Use when building REST APIs, Express/Fastify servers, microservices, or server-side TypeScript.

来源信息

仓库
iliaal/whetstone
最近来源活动
2026年2月27日 14:01
检测到的 SKILL.md 语言
英语
星标
36
分支
4

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
5 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
nodejs-backend
description
Node.js backend patterns: framework selection, layered architecture, TypeScript, validation, error handling, security, production deployment. Use when building REST APIs, Express/Fastify servers, microservices, or server-side TypeScript.
# Node.js Backend ## Framework Selection | Context | Choose | Why | |---------|--------|-----| | Edge/Serverless | Hono | Zero-dep, fastest cold starts | | Performance API | Fastify | 2-3x faster than Express, built-in schema validation | | Enterprise/team | NestJS | DI, decorators, structured conventions | | Legacy/ecosystem | Express | Most middleware, widest adoption | Ask user: deployment target, cold start needs, team experience, existing codebase. ## Architecture ``` src/ ├── routes/ # HTTP: parse request, call service, format response ├── middleware/ # Auth, validation, rate limiting, logging ├── services/ # Business logic (no HTTP types) ├── repositories/ # Data access only (queries, ORM) ├── config/ # Env, DB pool, constants └── types/ # Shared TypeScript interfaces ``` - Routes never contain business logic - Services never import Request/Response - Repositories never throw HTTP errors - For scripts/prototypes: single file is fine — ask "will this grow?" ## TypeScript Rules - Use `import type { }` for type-only imports — eliminates runtime overhead - Prefer `interface` for object shapes (2-5x faster type resolution than intersections) - Prefer `unknown` over `any` — forces explicit narrowing - Use `z.infer<typeof Schema>` as single source of truth — never duplicate types and schemas - Minimize `as` assertions — use type guards instead - Add explicit return types to exported functions (faster declaration emit) - Untyped package? `declare module 'pkg' { const v: unknown; export default v; }` in `types/ambient.d.ts` ## Validation **Zod** (TypeScript inference) or **TypeBox** (Fastify native). Validate at boundaries only: request entry, before DB ops, env vars at startup. Use `.extend()`, `.pick()`, `.omit()`, `.partial()`, `.merge()` for DRY schemas. ## Error Handling Custom error hierarchy: `AppError(message, statusCode, isOperational)` → `ValidationError(400)`, `NotFoundError(404)`, `UnauthorizedError(401)`, `ForbiddenError(403)`, `ConflictError(409)` Centralized handler middleware: - `AppError` → return `{ error: message }` with statusCode - Unknown → log full stack, return 500 + generic message in production - Async wrapper: `const asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);` Codes: 400 bad input | 401 no auth | 403 no permission | 404 missing | 409 conflict | 422 business rule | 429 rate limited | 500 server fault ## API Design - **Resources**: plural nouns (`/users`), max 2 nesting levels (`/users/:id/orders`) - **Methods**: GET read | POST create | PUT replace | PATCH partial | DELETE remove - **Versioning**: URL path `/api/v1/` - **Response**: `{ data, pagination?: { page, limit, total, totalPages } }` - **Errors**: `{ error: { code, message, details? } }` - **Queries**: `?page=1&limit=20&status=active&sort=createdAt,desc` - Return `Location` header on 201. Use 204 for successful DELETE with no body. ## Async Patterns | Pattern | Use When | |---------|----------| | `async/await` | Sequential operations | | `Promise.all` | Parallel independent ops | | `Promise.allSettled` | Parallel, some may fail | | `Promise.race` | Timeout or first-wins | Never `readFileSync` / sync methods in production. Offload CPU work to worker threads. Stream large payloads. ## Discipline - For non-trivial changes, pause and ask: "is there a more elegant way?" Skip for obvious fixes. - Simplicity first — every change as simple as possible, impact minimal code - Only touch what's necessary — avoid introducing unrelated changes - No hacky workarounds — if a fix feels wrong, step back and implement the clean solution ## References - [TypeScript config](references/typescript-config.md) — tsconfig, ESM, branded types, compiler performance - [Security](references/security.md) — JWT, password hashing, rate limiting, OWASP - [Database & production](references/database-production.md) — connection pooling, transactions, Docker, logging
在 GitHub 查看