From 9ebbf83f93d9797cb86b673597584b278e40ab84 Mon Sep 17 00:00:00 2001 From: lila Date: Sat, 21 Mar 2026 19:33:07 +0100 Subject: [PATCH] formatting --- apps/api/tsconfig.json | 6 +++--- apps/web/README.md | 22 +++++++++++----------- apps/web/tsconfig.app.json | 4 ++-- apps/web/tsconfig.json | 4 ++-- apps/web/tsconfig.node.json | 4 ++-- documentation/decisions.md | 18 ++++++++++++++++++ packages/db/tsconfig.json | 4 ++-- packages/shared/tsconfig.json | 4 ++-- pnpm-workspace.yaml | 2 +- tsconfig.base.json | 4 ++-- 10 files changed, 45 insertions(+), 27 deletions(-) diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index 52192c0..b470f84 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../tsconfig.base.json", "references": [ { "path": "../../packages/shared" }, - { "path": "../../packages/db" }, + { "path": "../../packages/db" } ], "compilerOptions": { "module": "NodeNext", @@ -10,7 +10,7 @@ "outDir": "./dist", "resolveJsonModule": true, "rootDir": ".", - "types": ["vitest/globals"], + "types": ["vitest/globals"] }, - "include": ["src", "vitest.config.ts"], + "include": ["src", "vitest.config.ts"] } diff --git a/apps/web/README.md b/apps/web/README.md index 7dbf7eb..db579d2 100644 --- a/apps/web/README.md +++ b/apps/web/README.md @@ -17,9 +17,9 @@ If you are developing a production application, we recommend updating the config ```js export default defineConfig([ - globalIgnores(['dist']), + globalIgnores(["dist"]), { - files: ['**/*.{ts,tsx}'], + files: ["**/*.{ts,tsx}"], extends: [ // Other configs... @@ -34,40 +34,40 @@ export default defineConfig([ ], languageOptions: { parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], + project: ["./tsconfig.node.json", "./tsconfig.app.json"], tsconfigRootDir: import.meta.dirname, }, // other options... }, }, -]) +]); ``` You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: ```js // eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' +import reactX from "eslint-plugin-react-x"; +import reactDom from "eslint-plugin-react-dom"; export default defineConfig([ - globalIgnores(['dist']), + globalIgnores(["dist"]), { - files: ['**/*.{ts,tsx}'], + files: ["**/*.{ts,tsx}"], extends: [ // Other configs... // Enable lint rules for React - reactX.configs['recommended-typescript'], + reactX.configs["recommended-typescript"], // Enable lint rules for React DOM reactDom.configs.recommended, ], languageOptions: { parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], + project: ["./tsconfig.node.json", "./tsconfig.app.json"], tsconfigRootDir: import.meta.dirname, }, // other options... }, }, -]) +]); ``` diff --git a/apps/web/tsconfig.app.json b/apps/web/tsconfig.app.json index e931dd8..a2c8d96 100644 --- a/apps/web/tsconfig.app.json +++ b/apps/web/tsconfig.app.json @@ -9,7 +9,7 @@ "noEmit": true, "target": "ES2023", "types": ["vite/client", "vitest/globals"], - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo" }, - "include": ["src", "vitest.config.ts"], + "include": ["src", "vitest.config.ts"] } diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 101b2d7..038f393 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -3,6 +3,6 @@ "references": [ { "path": "../../packages/shared" }, { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" }, - ], + { "path": "./tsconfig.node.json" } + ] } diff --git a/apps/web/tsconfig.node.json b/apps/web/tsconfig.node.json index a5e5c92..c32d427 100644 --- a/apps/web/tsconfig.node.json +++ b/apps/web/tsconfig.node.json @@ -8,7 +8,7 @@ "noEmit": true, "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2023", - "types": ["node"], + "types": ["node"] }, - "include": ["vite.config.ts"], + "include": ["vite.config.ts"] } diff --git a/documentation/decisions.md b/documentation/decisions.md index 0b322e2..a8da3b4 100644 --- a/documentation/decisions.md +++ b/documentation/decisions.md @@ -7,18 +7,23 @@ A record of non-obvious technical decisions made during development, with reason ## Tooling ### Monorepo: pnpm workspaces (not Turborepo) + Turborepo adds parallel task running and build caching on top of pnpm workspaces. For a two-app monorepo of this size, plain pnpm workspace commands are sufficient and there is one less tool to configure and maintain. ### TypeScript runner: `tsx` (not `ts-node`) + `tsx` is faster, requires no configuration, and uses esbuild under the hood. `ts-node` is older and more complex to configure. `tsx` does not do type checking — that is handled separately by `tsc` and the editor. Installed as a dev dependency in `apps/api` only. ### ORM: Drizzle (not Prisma) + Drizzle is lighter — no binary, no engine. Queries map closely to SQL. Migrations are plain SQL files. Works naturally with Zod for type inference. Prisma would add Docker complexity (engine binary in containers) and abstraction that is not needed for this schema. ### WebSocket: `ws` library (not Socket.io) + For rooms of 2–4 players, Socket.io's room management, transport fallbacks, and reconnection abstractions are unnecessary overhead. The WS protocol is defined explicitly as a Zod discriminated union in `packages/shared`, giving the same type safety guarantees. Reconnection logic is deferred to Phase 7. ### Auth: OpenAuth (not rolling own JWT) + All auth delegated to OpenAuth service at `auth.yourdomain.com`. Providers: Google, GitHub. The API validates the JWT on every protected request. User rows are created or updated on first login via the `sub` claim as the primary key. --- @@ -26,15 +31,19 @@ All auth delegated to OpenAuth service at `auth.yourdomain.com`. Providers: Goog ## Architecture ### Express app structure: factory function pattern + `app.ts` exports a `createApp()` factory function. `server.ts` imports it and calls `.listen()`. This allows tests to import the app directly without starting a server, keeping tests isolated and fast. ### Data model: `terms` + `translations` (not flat word pairs) + Words are modelled as language-neutral concepts with one or more translations per language. Adding a new language pair requires no schema changes — only new rows in `translations` and `language_pairs`. The flat `english/italian` column pattern is explicitly avoided. ### Multiplayer mechanic: simultaneous answers (not buzz-first) + All players see the same question at the same time and submit independently. The server waits for all answers or a 15-second timeout, then broadcasts the result. This keeps the experience Duolingo-like and symmetric. A buzz-first mechanic was considered and rejected. ### Room model: room codes (not matchmaking queue) + Players create rooms and share a human-readable code (e.g. `WOLF-42`) to invite friends. Auto-matchmaking via a queue is out of scope for MVP. Valkey is included in the stack and can support a queue in a future phase. --- @@ -42,15 +51,19 @@ Players create rooms and share a human-readable code (e.g. `WOLF-42`) to invite ## TypeScript Configuration ### Base config: no `lib`, `module`, or `moduleResolution` + These are intentionally omitted from `tsconfig.base.json` because different packages need different values — `apps/api` uses `NodeNext`, `apps/web` uses `ESNext`/`bundler` (Vite), and mixing them in the base caused errors. Each package declares its own. ### `outDir: "./dist"` per package + The base config originally had `outDir: "dist"` which resolved relative to the base file location, pointing to the root `dist` folder. Overridden in each package with `"./dist"` to ensure compiled output stays inside the package. ### `apps/web` tsconfig: deferred to Vite scaffold + The web tsconfig was left as a placeholder and filled in after `pnpm create vite` generated `tsconfig.json`, `tsconfig.app.json`, and `tsconfig.node.json`. The generated files were then trimmed to remove options already covered by the base. ### `rootDir: "."` on `apps/api` + Set explicitly to allow `vitest.config.ts` (which lives outside `src/`) to be included in the TypeScript program. Without it, TypeScript infers `rootDir` as `src/` and rejects any file outside that directory. --- @@ -58,12 +71,15 @@ Set explicitly to allow `vitest.config.ts` (which lives outside `src/`) to be in ## ESLint ### Two-config approach for `apps/web` + The root `eslint.config.mjs` handles TypeScript linting across all packages. `apps/web/eslint.config.js` is kept as a local addition for React-specific plugins only: `eslint-plugin-react-hooks` and `eslint-plugin-react-refresh`. ESLint flat config merges them automatically by directory proximity — no explicit import between them needed. ### Coverage config at root only + Vitest coverage configuration lives in the root `vitest.config.ts` only. Individual package configs omit it to produce a single aggregated report rather than separate per-package reports. ### `globals: true` with `"types": ["vitest/globals"]` + Using Vitest globals (`describe`, `it`, `expect` without imports) requires `"types": ["vitest/globals"]` in each package's tsconfig `compilerOptions`. Added to `apps/api`, `packages/shared`, and `packages/db`. Added to `apps/web/tsconfig.app.json`. --- @@ -71,6 +87,7 @@ Using Vitest globals (`describe`, `it`, `expect` without imports) requires `"typ ## Current State ### Completed checkboxes (Phase 0) + - [x] Initialise pnpm workspace monorepo: `apps/web`, `apps/api`, `packages/shared`, `packages/db` - [x] Configure TypeScript project references across packages - [x] Set up ESLint + Prettier with shared configs in root @@ -79,4 +96,5 @@ Using Vitest globals (`describe`, `it`, `expect` without imports) requires `"typ - [x] Scaffold Vite + React app with TanStack Router (single root route) — **in progress** ### Current checkpoint + Setting up TanStack Router in `apps/web` with a single root route. diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json index 3ed0091..0e85f05 100644 --- a/packages/db/tsconfig.json +++ b/packages/db/tsconfig.json @@ -5,7 +5,7 @@ "moduleResolution": "NodeNext", "outDir": "./dist", "resolveJsonModule": true, - "types": ["vitest/globals"], + "types": ["vitest/globals"] }, - "include": ["src", "vitest.config.ts"], + "include": ["src", "vitest.config.ts"] } diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 3ed0091..0e85f05 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -5,7 +5,7 @@ "moduleResolution": "NodeNext", "outDir": "./dist", "resolveJsonModule": true, - "types": ["vitest/globals"], + "types": ["vitest/globals"] }, - "include": ["src", "vitest.config.ts"], + "include": ["src", "vitest.config.ts"] } diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e0d3a5b..a081b79 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,5 +2,5 @@ packages: - apps/* - packages/* allowBuilds: - '@swc/core': true + "@swc/core": true esbuild: true diff --git a/tsconfig.base.json b/tsconfig.base.json index 2f5f8c1..b25b4b8 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -23,6 +23,6 @@ "sourceMap": true, "strict": true, "target": "es2022", - "verbatimModuleSyntax": true, - }, + "verbatimModuleSyntax": true + } }