This repo is a demo. Patterns here are suggestions to keep the example coherent; you should choose what fits your team.
- Prefer constructor/function injection for anything with side effects (DB, logger, auth, clock, external clients).
- Keep “wiring” at the edges (app startup / router factories). Avoid importing global singletons from deep inside services.
- Tests should be able to supply fakes or in-memory implementations without patching globals.
- Use structured logging (pino):
logger.info("message", { ...context }). - Log at boundaries (request → router → service), not inside hot loops.
- Never log secrets (tokens, passwords, raw cookies). Be careful with request/body logging.
- Treat errors as part of the API: model expected failures with custom errors (e.g.
NotFoundError,UnauthorizedError) rather than opaqueError. - Prefer explicit flows (e.g.
neverthrowResult) over throwing for control flow. - When catching unknown values, normalize them (e.g.
typedError(...)) before returning/logging. - Map internal errors to transport errors (HTTP/oRPC) intentionally; don’t leak internals to clients.
- Keep docs short and actionable: what/why/where + copy/paste commands.
- When changing workflows (dev, DB, testing, CI), update
README.mdand the relevantdocs/*.md. - Prefer linking to concrete files/paths over vague descriptions.
- Prefer unit/service tests that use DI (real DB when valuable; fakes when faster/clearer).
- If a test can fail due to timing, randomness, or shared state, fix the design or make the test deterministic.
- This repo’s shared testcontainers Postgres singleton is an experiment; we’ll keep evaluating whether it’s the right default.
LLMs are fine, but treat their output as untrusted input:
- Verify correctness and security; run
pnpm typecheckandpnpm test. - Don’t accept generated code that you don’t understand or can’t validate.
- Watch for subtle issues (validation gaps, error handling, logging secrets, SQL mistakes, license/provenance).