First commit, phased 1 and 2 created but untested
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# 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.
|
||||
- `const` by default; `let` only if reassigned; never `var`.
|
||||
- Names: `camelCase` functions/vars, `PascalCase` classes, `UPPER_SNAKE` constants, `snake_case` DB columns.
|
||||
- Convert DB `snake_case` rows → `camelCase` objects 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`:
|
||||
```js
|
||||
class AppError extends Error {
|
||||
constructor(code, message, status = 400) { super(message); this.code = code; this.status = status; }
|
||||
}
|
||||
```
|
||||
- Services throw `AppError` for expected failures (`new AppError('INSUFFICIENT_ENERGY','Not enough energy.',422)`).
|
||||
- Routes use an async wrapper so thrown errors reach `errorHandler`:
|
||||
```js
|
||||
const wrap = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
|
||||
```
|
||||
- `errorHandler` maps `AppError` → envelope; `ZodError` → 400 `VALIDATION_ERROR`; anything else → 500 generic message + server log.
|
||||
|
||||
## Pure game code
|
||||
- `src/game/*` exports plain functions; no I/O; no `Date.now()`; no `Math.random()` — take `rng` / `nowMs` params.
|
||||
- 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.js` exports a small `api(method, path, body)` wrapper that handles JSON, error envelope, and 401 → redirect to login.
|
||||
- DOM updates via `textContent` / `createElement`. No `innerHTML` with dynamic data.
|
||||
- One JS file per page + shared `api.js` and `ui.js` (toasts, formatting).
|
||||
- No global state beyond a single `state` object 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).
|
||||
Reference in New Issue
Block a user