2.3 KiB
2.3 KiB
CODING_STANDARDS.md
Language & style
- Node 20+, CommonJS,
'use strict'not needed in CJS modules but harmless. - 2-space indent, semicolons, single quotes, trailing commas in multiline literals.
constby default;letonly if reassigned; nevervar.- Names:
camelCasefunctions/vars,PascalCaseclasses,UPPER_SNAKEconstants,snake_caseDB columns. - Convert DB
snake_caserows →camelCaseobjects at the service boundary (one small mapper per entity). - Functions do one thing and fit on a screen (< 40 lines). Early returns over deep nesting.
- Comments explain why, not what. Add a one-line header comment to each file describing its purpose.
Errors
Create src/utils/errors.js:
class AppError extends Error {
constructor(code, message, status = 400) { super(message); this.code = code; this.status = status; }
}
- Services throw
AppErrorfor expected failures (new AppError('INSUFFICIENT_ENERGY','Not enough energy.',422)). - Routes use an async wrapper so thrown errors reach
errorHandler:
const wrap = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
errorHandlermapsAppError→ envelope;ZodError→ 400VALIDATION_ERROR; anything else → 500 generic message + server log.
Pure game code
src/game/*exports plain functions; no I/O; noDate.now(); noMath.random()— takerng/nowMsparams.- Return new objects instead of mutating inputs.
Database access
- One prepared statement per query, created once at module load (or lazily cached), not inside loops.
- Wrap multi-write operations in
db.transaction. - Never
SELECT *in services for public output; select what you return.
Frontend JS
public/js/api.jsexports a smallapi(method, path, body)wrapper that handles JSON, error envelope, and 401 → redirect to login.- DOM updates via
textContent/createElement. NoinnerHTMLwith dynamic data. - One JS file per page + shared
api.jsandui.js(toasts, formatting). - No global state beyond a single
stateobject per page.
Logging
src/utils/logger.js: tiny wrapper over console with levels; silent in tests unless LOG=1.
Dependencies
Pinned in package.json via npm install --save-exact. No dependency without need (NOTES.md §2.3).