
A boilerplate for Node.js apps / TypeScript
A TypeScript starter for applications that need account authentication, email verification, password recovery, image uploads, and background email delivery. Built with Express 5, TypeScript 7, MongoDB, Redis, and Zod, w…
以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。
A TypeScript starter for applications that need account authentication, email verification, password recovery, image uploads, and background email delivery. Built with Express 5, TypeScript 7, MongoDB, Redis, and Zod, with domain-owned modules and an OpenAPI 3.1 reference.
Version 2.0.0. Upgrading an existing installation? Start with the 1.x → 2.0 migration guide.
Quick start · API examples · Developer guide · Troubleshooting · Documentation index
Account workflows: JWT authentication, revocation, profile management, verification, and password recovery.
Domain-based code: local schemas, inferred DTOs, services, repositories, transformers, and utilities.
Background email: encrypted MongoDB outbox, a separate worker, retries, leases, and operator commands.
Customizable templates: server-owned HTML/plain-text templates, English/Georgian content, and language selection through Accept-Language.
Owned image uploads: JPEG/PNG ingestion, WebP avatars, and ownership checks.
Developer and deployment tooling: Swagger UI, TypeScript/ESLint/Prettier commands, and separate API/worker container definitions.
Quick start
- Prepare the dependencies
Install or provision these services before starting the application:
Account changes and email jobs commit in one transaction, so standalone MongoDB is insufficient. The application does not start MongoDB, Redis, or an SMTP relay for you.
nvm install nvm use node .yarn/releases/yarn-4.18.1.cjs --version node .yarn/releases/yarn-4.18.1.cjs install --immutable cp .env.example .env
Examples below use yarn. An existing Yarn/Corepack launcher selects the committed release through yarnPath; without a launcher, replace yarn with node .yarn/releases/yarn-4.18.1.cjs. Ordinary node_modules loading is retained. See tooling for CI, lifecycle scripts, production dependencies, and the TypeScript compatibility note.
Edit .env. The example configuration contains local defaults; configure these values for your environment:
Run the following command separately for each secret, then assign the outputs to JWT_SECRET and MAIL_QUEUE_ENCRYPTION_KEY in .env:
openssl rand -hex 32
Keep .env private and preserve the queue key across restarts and deployments. Existing encrypted jobs depend on it. SMTP authentication/TLS, secret files, custom URLs, and process-specific settings are covered in configuration.
For a new, empty database, provision collections and indexes before accepting traffic:
yarn db:indexes yarn dev
For existing data, follow the migration guide first. Index maintenance is an explicit database operation; installation and normal startup do not run it.
In another terminal, from the same repository root:
yarn dev:mail
The API persists email jobs; the worker renders and submits them through SMTP. Start both processes for complete account-email workflows.
With the local example settings, the expected addresses after startup are:
API readiness reports MongoDB/Redis state. Worker health and SMTP delivery are monitored separately.
These examples use the local configuration and illustrative responses. Replace the account credentials and returned tokens with your own. IDs, timestamps, and JWTs vary between requests.
API_BASE_URL=http://localhost:8000
curl -i "$API_BASE_URL/auth/sign-up"
-H 'Content-Type: application/json'
-H 'Accept-Language: ka-GE, ka;q=0.9, en;q=0.7'
--data '{"email":"developer@example.com","password":"ExamplePassword123!"}'
Successful response, HTTP 200:
{ "data": { "accessToken": "<JWT>" }, "messageKey": "auth.signed_up", "status": 200 }
Registration queues welcome and verification emails in the account transaction. Success confirms persistence; delivery proceeds asynchronously. Accept-Language selects email content, while the client translates the API's messageKey.
curl -i "$API_BASE_URL/auth/sign-in"
-H 'Content-Type: application/json'
--data '{"email":"developer@example.com","password":"ExamplePassword123!"}'
The response has the same token envelope with messageKey: "auth.signed_in". Copy data.accessToken from registration or sign-in:
ACCESS_TOKEN='<paste data.accessToken here>'
curl -i "$API_BASE_URL/me"
-H "Authorization: Bearer $ACCESS_TOKEN"
Example profile response, HTTP 200:
{ "data": { "_id": "507f1f77bcf86cd799439011", "email": "developer@example.com", "verified": false, "createdAt": "2026-11-01T12:00:00.000Z", "updatedAt": "2026-11-01T12:00:00.000Z" }, "messageKey": "users.profile_loaded", "status": 200 }
Profile names and an avatar URL appear when available. Password/email changes and email confirmation invalidate previous account JWTs; save the replacement token returned by those operations. Guest endpoints, including registration and sign-in, should omit Authorization.
A password shorter than six characters is rejected:
curl -i "$API_BASE_URL/auth/sign-up"
-H 'Content-Type: application/json'
--data '{"email":"developer@example.com","password":"short"}'
Response, HTTP 400:
{ "messageKey": "validation.failed", "status": 400, "details": [ { "path": "password", "messageKey": "validation.too_small", "params": { "min": 6, "inclusive": true, "origin": "string" } } ] }
Translate each key on the client and use path to associate field errors. Success envelopes contain optional data; errors contain optional details. HTTP status codes and machine keys describe outcomes. Responses include a server-generated X-Request-Id for correlation. See client integration for the full route map and JWT/link/upload workflows, and the message-key contract for translations.
Swagger covers authentication, verification, account management, media, template metadata, and health endpoints. It includes request/response schemas, authentication requirements, status codes, and workflow notes. Use the OpenAPI guide for the complete reference and export options.
The reference distinguishes required/optional bearer access from guest-only routes, derives path parameters from their schemas, and uses Zod input contracts for requests and output contracts for responses. JSON/form bodies, multipart failures, rate-limit headers, and raw health responses follow the HTTP implementation. Documentation metadata does not register routes or middleware.
Documentation is opt-in. DOCS_ENABLED=true enables /docs/, /docs/openapi.json, and /openapi.json. Interactive submission has its own setting, DOCS_TRY_IT_OUT_ENABLED, which defaults to false. Production documentation requires dedicated credentials and HTTPS; documentation credentials are separate from account JWTs.
Export a specification without starting services or providing database/JWT/SMTP credentials:
yarn docs:export --output openapi.json
The exporter refuses to overwrite an existing file. Choose a new output path for subsequent exports. Swagger assets are served locally, and external schema validation is disabled.
src/ index.ts app/ config/ Validated configuration by process role database/ MongoDB transactions and API Redis connection http/ Express composition, middleware, contracts, Swagger runtime/ API/worker lifecycles, logging, operator commands domains/ auth/ verification/ Email ownership confirmation users/ Account/profile persistence media/ Owned images and avatars; image.ts owns processing notifications/ preparation.ts Template-variable validation and locale selection renderer.ts HTML/text rendering and template initialization mailer.ts SMTP submission and failure classification delivery/ Outbox, leases, retries, worker, administration templates/ HTML/text templates, layout, partials translations/ Email dictionaries scripts/ Development entrypoints and build orchestration ops/ Containers, role environments, secret-file guidance docs/ Architecture, API, migration, operating guides
Each feature keeps its controllers, services, repositories, models, schemas.ts, dto.ts, transformer.ts, and local utils.ts together as needed. Domains expose an explicit index.ts API and public DTO/schema contracts. Verification remains inside auth; delivery remains inside notifications.
Schemas are the source of truth for data contracts: infer parsed DTOs with z.infer and pre-parse inputs with z.input. Reuse identical contracts and derive meaningful variants; do not create operation-specific aliases for the same shape. Native database/framework adapters keep their library types. See schema and DTO ownership.
transformer.ts is optional: use it for ID/date conversion, normalization, or a meaningful public-field boundary. Assemble simple response objects where they are produced. DTOs describe types; they do not transform or filter runtime values. See the decision rules.
Services add business rules and orchestration. Repository operations that already return the domain contract can be exposed through direct function references in the public facade, without another forwarding function. See service/repository boundaries.
Small HTTP handlers can live directly in a domain router; create a controller when input/context adaptation warrants it. See controllers and middleware for response helpers, guards, and composition rules.
Keep utils.ts focused on small local helpers. Image processing, notification preparation/rendering, and SMTP behavior have named modules within their owning domains; the utility ownership map documents their boundaries.
Relative source imports use .ts; TypeScript rewrites them to .js in dist/. The build compiler is TypeScript 7.0.2 under @typescript/native; typescript pins the complete 6.0.3 JavaScript SDK required by ESLint tooling. Using the SDK directly avoids Yarn patching a compatibility re-export package and fixes YN0066. See tooling and architecture.
For new domains and endpoints, follow the developer guide: schemas → DTOs → persistence → service → middleware/controller → routes → Swagger, including registration points and extension rules. Use the QA and release handoff guide to transfer the feature with explicit acceptance expectations and evidence.
Run yarn build before compiled commands. Build output is in dist/; uploads remain in the configured persistent storage directory. Queue retry, index creation, and legacy migration change state; select the intended environment before invoking them.
Symptom What to inspect and how to resolve it
Startup reports CONFIG_INVALID Correct all listed settings for this process in .env or its environment. Each issue includes an explanation; do not configure both a nonempty secret and its _FILE counterpart. See runtime diagnostics.
MongoDB connection fails or account transactions are rejected Check reachability, credentials, replica-set discovery/name, and transaction support. Use a replica set or Atlas; create collections/indexes before writes. See database.
Startup fails at redis, or readiness returns 503 Restore MongoDB/Redis connectivity and check URI/TLS settings. Redis also backs rate limits and revocation; API readiness does not describe SMTP health.
Swagger returns 404 or requests documentation credentials Set DOCS_ENABLED=true and restart the API. If docs credentials are configured, use their dedicated HTTP Basic login; production requires them. See OpenAPI.
Authentication returns 401, or sign-in/sign-up returns 403 Use a current bearer JWT for authenticated routes. Save replacement tokens after security changes, and omit Authorization on guest routes.
Requests return 429 during repeated manual calls Respect Retry-After and the configured rate-limit window. Check the separate sensitive-route limit and trusted-proxy settings before adjusting development limits.
Emails remain queued Run yarn mail:queue stats and yarn mail:queue workers. Start/restore the separate worker and inspect its logs, job deadlines, and SMTP availability.
Jobs fail with payload.invalid Restore the original queue key shared by the API and worker. Changing the key does not re-encrypt existing jobs. Follow the queue recovery guide.
Jobs fail with render.failed or smtp.configuration
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。