|
1 | | -# Copilot Instructions |
| 1 | +# GitHub Copilot Instructions |
2 | 2 |
|
3 | | -## Stack |
| 3 | +## Overview |
| 4 | + |
| 5 | +REST API for managing football players built with Node.js and Express.js in TypeScript (native ESM). Implements CRUD operations with a layered architecture, Sequelize ORM + SQLite, in-memory caching, Swagger documentation, and Pino structured logging. Part of a cross-language comparison study (.NET, Go, Java, Python, Rust). |
| 6 | + |
| 7 | +## Tech Stack |
4 | 8 |
|
5 | 9 | - **Runtime**: Node.js 24 LTS (Krypton) |
| 10 | +- **Language**: TypeScript (strict mode, native ESM) |
6 | 11 | - **Framework**: Express.js 5 |
7 | | -- **Language**: TypeScript (strict mode) |
8 | | -- **Database**: SQLite with Sequelize ORM |
9 | | -- **Testing**: Jest 30 with Supertest |
10 | | -- **Containerization**: Docker with multi-stage builds |
11 | | - |
12 | | -## Project Patterns |
13 | | - |
14 | | -- **Layered Architecture**: Routes → Controllers → Services → Database |
15 | | -- **Dependency Injection**: Constructor injection with interface-based abstractions |
16 | | -- **Error Handling**: Try/catch in controllers, centralized error middleware |
17 | | -- **Caching**: In-memory node-cache (1-hour TTL) at service layer |
18 | | -- **Logging**: Pino structured logging with request correlation IDs |
19 | | -- **Security**: Helmet middleware for headers, CORS, express-rate-limit |
20 | | - |
21 | | -## Code Conventions |
22 | | - |
23 | | -- **Module System**: Native ESM (not CommonJS) - always include `.js` in relative imports |
24 | | -- **Naming**: camelCase for variables/functions, PascalCase for classes/types/interfaces |
25 | | -- **File Naming**: kebab-case with suffixes (`player-service.ts`, `player-controller.ts`) |
26 | | -- **Imports**: Group by external deps → internal modules → types, alphabetically sorted |
27 | | -- **Type Safety**: Strict TypeScript, avoid `any` unless justified, prefer interfaces over types |
28 | | -- **Async**: All I/O operations use async/await, never callbacks or synchronous calls |
29 | | -- **Comments**: JSDoc for public APIs and Swagger annotations, inline comments only when necessary |
30 | | -- **Formatting**: Prettier (4 spaces, single quotes, 127 width) - enforced pre-commit |
31 | | -- **Commit Messages**: Conventional Commits format `type(scope): description (#issue)` (max 80 chars) |
32 | | - |
33 | | -## Testing |
34 | | - |
35 | | -- **Structure**: Integration tests in `/tests/`, focus on controller/service/route layers |
36 | | -- **Naming Convention**: Action-oriented pattern with visual flow |
37 | | - |
38 | | - ```typescript |
39 | | - it('Request {METHOD} {/path} {context} → Response {outcome}', async () => { |
40 | | - ``` |
41 | | -
|
42 | | - - Example: `it('Request GET /players/{id} existing → Response status 200 OK', async () => {` |
43 | | - - **Components**: Request/Response (Title Case), METHOD (ALL CAPS), /path (actual endpoint), context (lowercase), outcome (status codes in Title Case like `200 OK`, `404 Not Found`) |
44 | | -- **Mocking**: Use Jest mocks for external dependencies, avoid mocking internal modules |
45 | | -- **Coverage**: Maintain existing coverage levels (controllers, services, routes only) |
46 | | -- **Runner**: Jest with ESM support (`ts-jest` preset), use `--watch` in development |
47 | | -
|
48 | | -## Avoid |
49 | | -
|
50 | | -- Using `any` type without explicit justification |
51 | | -- Missing `.js` extensions in relative imports (ESM breaks without them) |
52 | | -- Mixing CommonJS (`require`/`module.exports`) with ESM (`import`/`export`) |
53 | | -- Synchronous file operations (`fs.readFileSync`, `fs.writeFileSync`) |
54 | | -- Missing error handling on async operations (always `try/catch`) |
55 | | -- Using `console.log` instead of Pino logger |
56 | | -- Creating files without interfaces when abstraction is needed |
57 | | -- Ignoring TypeScript errors or using `@ts-ignore` without comments |
58 | | -- Mocking Sequelize models in tests (use real test database) |
| 12 | +- **ORM**: Sequelize |
| 13 | +- **Database**: SQLite |
| 14 | +- **Caching**: node-cache (in-memory, 1-hour TTL) |
| 15 | +- **Logging**: Pino (structured, with request correlation IDs) |
| 16 | +- **Security**: Helmet, CORS, express-rate-limit |
| 17 | +- **Testing**: Jest 30 + Supertest |
| 18 | +- **Linting/Formatting**: ESLint + Prettier |
| 19 | +- **API Docs**: Swagger (JSDoc annotations → swagger.json) |
| 20 | +- **Containerization**: Docker (multi-stage builds) |
| 21 | + |
| 22 | +## Structure |
| 23 | + |
| 24 | +```text |
| 25 | +src/ |
| 26 | +├── controllers/ — request handlers + Swagger JSDoc + try/catch [HTTP layer] |
| 27 | +├── routes/ — Express Router definitions + middleware |
| 28 | +├── services/ — business logic + node-cache caching [business layer] |
| 29 | +├── database/ — Sequelize interfaces + implementations [data layer] |
| 30 | +├── models/ — Sequelize Player model |
| 31 | +├── middlewares/ — rate limiter, validators, CSP |
| 32 | +├── docs/ — Swagger config and doc generation |
| 33 | +└── utils/ — Pino logging configuration |
| 34 | +tests/ — Jest + Supertest integration tests |
| 35 | +storage/ — pre-seeded SQLite database (versioned, used in Docker image) |
| 36 | +scripts/ — Docker entrypoint and healthcheck scripts |
| 37 | +``` |
| 38 | + |
| 39 | +**Layer rule**: `Routes → Controllers → Services → Database`. Controllers must not contain business logic. Services handle all caching and Sequelize operations. |
| 40 | + |
| 41 | +## Coding Guidelines |
| 42 | + |
| 43 | +- **Module system**: Native ESM — always include `.js` extension in relative imports (omitting it breaks ESM at runtime) |
| 44 | +- **Naming**: camelCase (variables/functions), PascalCase (classes/types/interfaces), kebab-case (file names, e.g. `player-service.ts`) |
| 45 | +- **Type safety**: Strict TypeScript; never use `any`; prefer interfaces over types |
| 46 | +- **DI**: Constructor injection with interface-based abstractions |
| 47 | +- **Async**: All I/O uses async/await; never callbacks or synchronous calls |
| 48 | +- **Logging**: Pino only; never `console.log` |
| 49 | +- **Imports**: Group external deps → internal modules → types; alphabetically sorted within groups |
| 50 | +- **Formatting**: Prettier (4 spaces, single quotes, 127 width) — enforced pre-commit |
| 51 | +- **Tests**: naming `it('Request {METHOD} {/path} {context} → Response {outcome}')` — METHOD ALL CAPS, status codes Title Case (e.g. `200 OK`, `404 Not Found`); mock external deps only; use real test database (no Sequelize mocking) |
| 52 | +- **Avoid**: `any` without justification, missing `.js` in imports, mixing CommonJS with ESM, sync file ops, `console.log`, `@ts-ignore` without comments, mocking Sequelize models |
| 53 | + |
| 54 | +## Commands |
| 55 | + |
| 56 | +### Quick Start |
| 57 | + |
| 58 | +```bash |
| 59 | +npm install |
| 60 | +npm run dev # http://localhost:9000 |
| 61 | +npm run build && npm start |
| 62 | +npm test # all tests |
| 63 | +npm run coverage # tests + coverage |
| 64 | +npm run lint |
| 65 | +npx tsc --noEmit # type check |
| 66 | +npx prettier --write . |
| 67 | +docker compose up |
| 68 | +docker compose down -v |
| 69 | +``` |
| 70 | + |
| 71 | +### Pre-commit Checks |
| 72 | + |
| 73 | +1. Update `CHANGELOG.md` `[Unreleased]` section (Added / Changed / Fixed / Removed) |
| 74 | +2. `npm run lint` — ESLint must pass |
| 75 | +3. `npx tsc --noEmit` — TypeScript must compile clean |
| 76 | +4. `npm run coverage` — all tests must pass, coverage maintained |
| 77 | +5. `npm run lint:commit` — Conventional Commits validation |
| 78 | +6. Commit message follows Conventional Commits format (enforced by commitlint) |
| 79 | + |
| 80 | +### Commits |
| 81 | + |
| 82 | +Format: `type(scope): description (#issue)` — max 80 chars |
| 83 | +Types: `feat` `fix` `chore` `docs` `test` `refactor` `ci` `perf` |
| 84 | +Example: `feat(api): add player stats endpoint (#42)` |
| 85 | + |
| 86 | +## Agent Mode |
| 87 | + |
| 88 | +### Proceed freely |
| 89 | + |
| 90 | +- Route handlers and controllers |
| 91 | +- Service layer logic and caching |
| 92 | +- Unit and integration tests |
| 93 | +- Documentation updates |
| 94 | +- Code quality and formatting improvements |
| 95 | + |
| 96 | +### Ask before changing |
| 97 | + |
| 98 | +- Database schema (Sequelize model fields) |
| 99 | +- Dependencies (`package.json`) |
| 100 | +- Node.js version (`.nvmrc`, `package.json engines`) |
| 101 | +- CI/CD configuration (`.github/workflows/`) |
| 102 | +- Docker setup |
| 103 | +- Environment variables |
| 104 | +- API contracts (breaking changes) |
| 105 | + |
| 106 | +### Never modify |
| 107 | + |
| 108 | +- `.env` files |
| 109 | +- `storage/players-sqlite3.db` (pre-seeded, versioned, used in Docker image) |
| 110 | +- Generated files (`dist/`, `coverage/`, `swagger.json`) |
| 111 | +- Port configuration (9000) |
| 112 | +- Production configurations or deployment secrets |
| 113 | + |
| 114 | +### Key workflows |
| 115 | + |
| 116 | +**Add an endpoint**: Create interface + implementation in `src/controllers/` with Swagger JSDoc + try/catch → add service logic in `src/services/` with caching + Sequelize operations → register route in `src/routes/` → add integration tests following naming convention → run `npm run swagger:docs` → run pre-commit checks. |
| 117 | + |
| 118 | +**Modify schema**: Update Sequelize model in `src/models/` → manually update `storage/players-sqlite3.db` (no migration system) → rebuild Docker image with `docker compose build` → update services, controllers, and tests → run `npm run coverage`. |
| 119 | + |
| 120 | +**Cross-repo consistency**: API contracts (endpoints, schemas, HTTP status codes), release naming (football terminology, alphabetical), and CI/CD patterns must stay consistent across all stacks. |
| 121 | + |
| 122 | +**After completing work**: Suggest a branch name (e.g. `feat/add-player-stats`) and a commit message following Conventional Commits including co-author line: |
| 123 | + |
| 124 | +```text |
| 125 | +feat(scope): description (#issue) |
| 126 | +
|
| 127 | +Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
| 128 | +``` |
0 commit comments