From 28dcc164724f899e63df25b7b76f657426e99e13 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sun, 19 Apr 2026 17:12:31 +0200 Subject: [PATCH] docs: harmonize project memories with current codebase state - Add UI Common and CLI sections to all 4 memories - Fix UI Common build = typecheck (source-only package, no artifacts) - Fix monorepo description: 4 TS packages (pnpm) + 1 Python (Poetry) - Fix OCPP Server coverage threshold column placement - Flag Vitest watch mode in commands and checklist - Add Zod dependency and config validation convention - Fix source tree comment (3 transports, not 2) - Update CI matrix to Python 3.13/3.14 - Add CLI conventions (factory pattern, payload helpers, short hash, output) - Add UI Common conventions (canonical types, no re-exports, errors) - Add per-framework testing conventions (root strict vs ui assert vs vitest) - Refactor checklist to remove command duplication with suggested_commands - Fix README references to actual project files --- .serena/memories/code_style_conventions.md | 46 ++++++- .serena/memories/project_overview.md | 48 ++++--- .serena/memories/suggested_commands.md | 129 ++++++++++-------- .serena/memories/task_completion_checklist.md | 77 ++++++----- 4 files changed, 183 insertions(+), 117 deletions(-) diff --git a/.serena/memories/code_style_conventions.md b/.serena/memories/code_style_conventions.md index df90126e..401a9b30 100644 --- a/.serena/memories/code_style_conventions.md +++ b/.serena/memories/code_style_conventions.md @@ -76,15 +76,40 @@ - **Auto-reload**: file watcher on `src/assets/config.json` - **Sections**: `log`, `storage`, `uiServer`, `worker`, `stationTemplateUrls`, `supervisionUrls` +## UI Common Conventions + +- **Shared library**: Types, WebSocket client, adapters, utilities shared between ui/web and ui/cli +- **Canonical types**: `ChargingStationData`, `ConnectorEntry`, `EvseEntry`, `SimulatorState`, `ResponsePayload`, `ProcedureName` — all consumers import directly from `ui-common` +- **Errors**: `ConnectionError`, `ServerFailureError`, `extractErrorMessage` centralized in `errors.ts` +- **Constants**: `DEFAULT_HOST`, `DEFAULT_PORT`, `DEFAULT_PROTOCOL`, `DEFAULT_PROTOCOL_VERSION`, `DEFAULT_SECURE` in `constants.ts` +- **Utilities**: `convertToBoolean()`, `convertToInt()`, `getWebSocketStateName()`, `randomUUID()`, `validateUUID()` — shared, not duplicated in consumers +- **Config validation**: Zod schemas in `src/config/schema.ts` validate UI server configuration. Update schemas alongside type changes +- **No re-exports**: Consumers import directly from `ui-common`, not through intermediate barrels +- **Tests**: `node:test` + `node:assert` (not vitest) + +## CLI Conventions + +- **Command factory pattern**: Each command module exports `createXxxCommands(program): Command` — returns a `Command`, registered via `program.addCommand()` +- **Declarative registry**: Simple commands with identical structure use a loop over a `[name, description, procedureName][]` array +- **Payload helpers**: `buildHashIdsPayload()`, `pickDefined()`, `pickPresent()`, `PAYLOAD_OPTION`, `PAYLOAD_DESC` in `payload.ts` +- **Short hash resolution**: Hash ID prefixes resolved via station list lookup before command execution (transparent to user) +- **Human output**: Borderless tables via `cli-table3`, status icons, truncated hash IDs, fuzzy timestamps. Renderers dispatch by payload shape via type guards +- **Output convention**: success → stdout, errors → stderr, `--json` → structured JSON on stdout +- **Embedded skill**: SKILL.md embedded at build time via esbuild define, served by `skill show`/`skill install` +- **Tests**: `node:test` + `node:assert`, shared `captureStream` helper in `tests/helpers.ts` +- **Semantic descriptions**: "Request station(s) to send OCPP X" (not "Send OCPP X") — the CLI instructs the simulator, which instructs the station + ## Vue UI Conventions - **Route names**: Use `ROUTE_NAMES` constant object from `composables/Constants.ts` — never hardcode route strings - **Placeholders**: Use `EMPTY_VALUE_PLACEHOLDER` constant for unknown/missing values — never hardcode `'Ø'` - **localStorage keys**: Use `UI_SERVER_CONFIGURATION_INDEX_KEY` and `TOGGLE_BUTTON_KEY_PREFIX` constants -- **Separate package**: UI Web cannot import from the backend `src/` — shared logic is duplicated in `composables/Utils.ts` +- **Separate package**: UI Web cannot import from the backend `src/` — shared logic lives in `ui-common`, web-specific composables in `composables/Utils.ts` ## Testing Conventions +### Root Simulator (`tests/`) + Full guide: `tests/TEST_STYLE_GUIDE.md`. Key points: - **Assertions**: `node:assert/strict` — strict only; `assert.ok` only for boolean/existence; never loose equality @@ -101,6 +126,23 @@ Full guide: `tests/TEST_STYLE_GUIDE.md`. Key points: - **Direct imports**: Test files import from the defining module, not through re-export hubs. `src/` barrels remain (public API) - **`__testable__` pattern**: `ocpp/1.6/__testable__/` and `ocpp/2.0/__testable__/` directories expose internal classes (e.g., `OCPP20VariableManagerTestable`, `OCPP20RequestServiceTestable`) for unit testing private internals. Import from `__testable__/index.ts` barrel in tests only +### UI Common & CLI (`ui/common/tests/`, `ui/cli/tests/`) + +- **Framework**: `node:test` + `node:assert` (not strict, not vitest) +- **Structure**: `await describe()` / `await it()` pattern +- **Naming**: files as `module-name.test.ts`, tests as `'should ...'` or descriptive phrase +- **Shared helpers**: `captureStream()` in `ui/cli/tests/helpers.ts` for stdout/stderr capture +- **Data**: Use canonical types from `ui-common` with proper enum values in test fixtures + +### Web UI (`ui/web/tests/`) + +- **Framework**: Vitest + `@vue/test-utils` +- **Assertions**: `expect()` (Vitest API) +- **Mocking**: `vi.mock()` for modules, `vi.fn()` for functions, `vi.mocked()` for typed access +- **Router**: Mock `vue-router` via `vi.mock('vue-router')` for components using `useRoute`/`useRouter` +- **Toast**: Global `toastMock` in `tests/setup.ts` +- **File headers**: Mandatory `@file` + `@description` JSDoc + ## Python Conventions (tests/ocpp-server/) - **Naming**: SCREAMING_SNAKE_CASE constants with unit suffixes (`_SECONDS`), snake_case functions, PascalCase classes @@ -114,6 +156,6 @@ Full guide: `tests/TEST_STYLE_GUIDE.md`. Key points: ## Common Pitfalls - **ESLint cache**: Clear `.eslintcache` if lint results seem stale after config changes -- **Web UI is independent**: Always run its quality gates separately from `ui/web/` directory +- **UI sub-projects are independent**: Always run quality gates separately from `ui/common/`, `ui/cli/`, `ui/web/` directories - **OCPP server is Python**: Uses Poetry, not pnpm. Linter is ruff (not pylint/flake8). Type checker is mypy - **Barrel circular deps**: `src/utils/` must NOT import from `src/exception/index.js` diff --git a/.serena/memories/project_overview.md b/.serena/memories/project_overview.md index 352e3bdf..c2dfc8fc 100644 --- a/.serena/memories/project_overview.md +++ b/.serena/memories/project_overview.md @@ -4,28 +4,32 @@ Node.js simulator for OCPP-J charging stations, part of SAP e-Mobility solution. Simulates and scales charging stations for load testing and development. -## Monorepo Structure (pnpm workspace) +## Monorepo Structure -3 sub-projects: +4 TypeScript packages (pnpm workspace) + 1 Python project (Poetry, independent): 1. **Root Simulator** (`/`) — Node.js/TypeScript OCPP simulator (main project) -2. **Web UI** (`/ui/web`) — Vue 3 + Vite dashboard for monitoring/control -3. **OCPP Mock Server** (`/tests/ocpp-server`) — Python OCPP 2.0.1 mock server for testing +2. **UI Common** (`/ui/common`) — Shared TypeScript library (types, WebSocket client, utilities) for UI packages +3. **Web UI** (`/ui/web`) — Vue 3 + Vite dashboard for monitoring/control +4. **CLI** (`/ui/cli`) — Command-line tool for managing the simulator (Commander.js, esbuild bundled) +5. **OCPP Mock Server** (`/tests/ocpp-server`) — Python OCPP 2.0.1 mock server for testing ## Tech Stack -| Sub-project | Runtime | Language | Package Manager | Test Framework | Build Tool | -| ----------- | ---------------- | ------------------------ | --------------- | ----------------------- | ---------- | -| Simulator | Node.js >=22.0.0 | TypeScript 6.0 | pnpm >=10.9.0 | Node.js native `--test` | esbuild | -| Web UI | Node.js >=22.0.0 | TypeScript 6.0 + Vue 3.5 | pnpm >=10.9.0 | Vitest | Vite 8 | -| OCPP Server | Python >=3.12 | Python | Poetry >=2.0 | pytest + pytest-asyncio | N/A | +| Sub-project | Runtime | Language | Package Manager | Test Framework | Build Tool | +| ----------- | ---------------- | ------------------------ | --------------- | ----------------------- | ----------------- | +| Simulator | Node.js >=22.0.0 | TypeScript 6.0 | pnpm >=10.9.0 | Node.js native `--test` | esbuild | +| UI Common | Node.js >=22.0.0 | TypeScript 6.0 | pnpm >=10.9.0 | Node.js native `--test` | N/A (source-only) | +| Web UI | Node.js >=22.0.0 | TypeScript 6.0 + Vue 3.5 | pnpm >=10.9.0 | Vitest | Vite 8 | +| CLI | Node.js >=22.0.0 | TypeScript 6.0 | pnpm >=10.9.0 | Node.js native `--test` | esbuild | +| OCPP Server | Python >=3.12 | Python | Poetry >=2.0 | pytest + pytest-asyncio | N/A | ## Coverage Thresholds -| Sub-project | Branches | Functions | Lines/Statements | -| ----------- | ------------- | --------- | ---------------- | -| Web UI | 89% | 83% | 91% | -| OCPP Server | 83% (overall) | — | — | +| Sub-project | Branches | Functions | Lines/Statements | +| ----------- | -------- | --------- | ----------------------------- | +| Web UI | 89% | 83% | 91% | +| OCPP Server | — | — | 83% (fail_under, branch=true) | ## Source Structure @@ -38,7 +42,7 @@ src/ │ │ ├── auth/ # Authentication subsystem (barrel: index.ts) │ │ └── index.ts # OCPP barrel │ ├── broadcast-channel/ # Worker communication -│ ├── ui-server/ # UI server (HTTP + WebSocket) +│ ├── ui-server/ # UI server (WebSocket, MCP, HTTP) │ └── index.ts # Charging station barrel ├── types/ # Type definitions (barrel: index.ts) │ └── ocpp/ # OCPP-specific types (1.6/, 2.0/) @@ -74,13 +78,7 @@ src/ ## Auth Subsystem (`ocpp/auth/`) -- **OCPPAuthServiceImpl**: Strategy priority chain (local → remote → certificate) -- **3 strategies**: LocalAuthStrategy (cache + local auth list lookup), RemoteAuthStrategy (CSMS network calls), CertificateAuthStrategy (X.509) -- **InMemoryAuthCache**: LRU with TTL, rate limiting, periodic cleanup -- **InMemoryLocalAuthListManager**: CSMS-managed authorization list with Full/Differential updates, version tracking, capacity limits -- **AuthComponentFactory**: Creates adapters, strategies, caches, managers from config -- **AuthHelpers**: Cross-version utility functions (TTL calculation, result formatting, logging sanitization) -- **Version adapters**: OCPP16AuthAdapter, OCPP20AuthAdapter +Strategy pattern with priority chain: local (cache + auth list) → remote (CSMS) → certificate (X.509). Independent subsystem with its own barrel, factory, version adapters (OCPP16/20), LRU cache with TTL, and rate limiting. ## UI Server (`ui-server/`) @@ -110,7 +108,9 @@ tests/ | ----------- | ---------------------- | ----------------------- | -------------------- | | Simulator | Ubuntu, macOS, Windows | Node 22.x, 24.x, latest | Ubuntu + Node 24.x | | Web UI | Ubuntu, macOS, Windows | Node 22.x, 24.x, latest | Ubuntu + Node 24.x | -| OCPP Server | Ubuntu, macOS, Windows | Python 3.12, 3.13 | Ubuntu + Python 3.13 | +| UI Common | Ubuntu | Node 24.x | Ubuntu + Node 24.x | +| CLI | Ubuntu, macOS, Windows | Node 22.x, 24.x, latest | Ubuntu + Node 24.x | +| OCPP Server | Ubuntu, macOS, Windows | Python 3.13, 3.14 | Ubuntu + Python 3.14 | Gated steps (lint, typecheck, coverage, SonarCloud) run only on the gated platform. Build + test run on all platforms. @@ -134,4 +134,8 @@ docs/ - **winston** — Logging with daily rotation - **@mikro-orm/** — Database ORM (SQLite, MariaDB) - **mnemonist** — Data structures (CircularBuffer) +- **zod** — Schema validation (UI Common config) +- **commander** — CLI command framework +- **cli-table3** — CLI table rendering +- **chalk** — CLI terminal colors - **websockets** + **ocpp** — Python OCPP mock server diff --git a/.serena/memories/suggested_commands.md b/.serena/memories/suggested_commands.md index acd16866..d565d89b 100644 --- a/.serena/memories/suggested_commands.md +++ b/.serena/memories/suggested_commands.md @@ -5,7 +5,7 @@ ### Install & Build ```bash -pnpm install # Install all dependencies (root + ui/web) +pnpm install # Install all dependencies (root + ui/common + ui/cli + ui/web) pnpm build # Production build (esbuild) pnpm build:dev # Development build with source maps pnpm clean:dist # Remove dist/ @@ -38,21 +38,69 @@ pnpm test:coverage # Tests with LCOV coverage → coverage/lcov.inf --- -## Web UI (`/ui/web`) +## UI Common (`/ui/common`) -**IMPORTANT**: This is a separate sub-project. Run commands from `ui/web/` directory. +**IMPORTANT**: Shared library. Run commands from `ui/common/` directory. Build this first — ui/cli and ui/web depend on it. -### Install & Build +### Build & Quality ```bash -cd ui/web -pnpm build # Vite production build -pnpm clean:dist # Remove dist/ +cd ui/common +pnpm build # Typecheck (same as typecheck — no build artifacts, source-only package) +pnpm typecheck # tsc --noEmit (identical to build) +pnpm lint # ESLint check only +pnpm format # Prettier + ESLint auto-fix +pnpm test # Node.js native test runner (node:test + node:assert) +pnpm test:coverage # Tests with coverage +``` + +--- + +## CLI (`/ui/cli`) + +**IMPORTANT**: Separate sub-project. Run commands from `ui/cli/` directory. Depends on ui/common. + +### Build & Quality + +```bash +cd ui/cli +pnpm build # esbuild bundle → dist/cli.js +pnpm typecheck # tsc --noEmit +pnpm lint # ESLint check only +pnpm format # Prettier + ESLint auto-fix +pnpm test # Node.js native test runner (node:test + node:assert) +pnpm test:coverage # Tests with coverage +pnpm test:integration # Integration tests (requires built CLI) ``` ### Run ```bash +node dist/cli.js --help # Show help +node dist/cli.js --config station list # List stations with config +node dist/cli.js --json simulator state # Get state in JSON mode +node dist/cli.js skill show # Print embedded agent skill +node dist/cli.js skill install # Install agent skill locally +``` + +### Features + +- **Short hash prefix matching**: Use truncated hash IDs (e.g., `e9041c`) instead of full 96-char hashes +- **Custom payloads**: `-p '{"key":"val"}'`, `-p @file.json`, or stdin via `-p -` +- **Human output**: Borderless tables with status icons, colors, connector info +- **JSON output**: `--json` flag for machine-readable output + +--- + +## Web UI (`/ui/web`) + +**IMPORTANT**: Separate sub-project. Run commands from `ui/web/` directory. Depends on ui/common. + +### Build & Run + +```bash +cd ui/web +pnpm build # Vite production build pnpm dev # Vite dev server with hot-reload (port 5173) pnpm start # Build + serve via Node.js HTTP server (port 3030) pnpm preview # Build + Vite preview @@ -64,37 +112,26 @@ pnpm preview # Build + Vite preview pnpm format # Prettier + ESLint auto-fix pnpm typecheck # vue-tsc type checking (no emit) pnpm lint # ESLint check only -pnpm lint:fix # ESLint auto-fix only -``` - -### Test - -```bash -pnpm test # Run Vitest tests -pnpm test:coverage # Vitest with V8 coverage +pnpm test # Vitest (watch mode locally — use `vitest run` for single-run) +pnpm test:coverage # Vitest single-run with V8 coverage ``` --- ## OCPP Mock Server (`/tests/ocpp-server`) -**IMPORTANT**: This is a Python sub-project. Uses Poetry for dependency management. +**IMPORTANT**: Python sub-project. Uses Poetry, not pnpm. -### Install +### Install & Run ```bash cd tests/ocpp-server -poetry install --no-root # Install dependencies -``` - -### Run - -```bash -poetry run task server # Start server (127.0.0.1:9000) -poetry run python server.py --host 0.0.0.0 --port 8080 # Custom host/port -poetry run python server.py --boot-status rejected # Custom boot status -poetry run python server.py --auth-mode whitelist --whitelist token1 token2 -poetry run python server.py --command GetBaseReport --period 5 +poetry install --no-root +poetry run task server # Start (127.0.0.1:9000) +poetry run python server.py --host 0.0.0.0 --port 8080 # Custom host/port +poetry run python server.py --boot-status rejected # Custom boot status +poetry run python server.py --auth-mode whitelist --whitelist t1 t2 # Auth mode +poetry run python server.py --command GetBaseReport --period 5 # Periodic command ``` ### Code Quality @@ -103,44 +140,28 @@ poetry run python server.py --command GetBaseReport --period 5 poetry run task format # Ruff auto-fix + format poetry run task typecheck # Mypy type check poetry run task lint # Ruff check + format check -``` - -### Test - -```bash -poetry run task test # Run pytest -poetry run task test_coverage # Pytest with coverage report +poetry run task test # pytest +poetry run task test_coverage # pytest with coverage ``` --- ## Pre-Commit Hooks (automatic on `git commit`) -1. **lint-staged**: Prettier + ESLint on staged files (root + ui/web + ocpp-server) -2. **commitlint**: Enforces Conventional Commits format on commit messages +1. **lint-staged**: Prettier + ESLint on staged files (root + ui/\* + ocpp-server) +2. **commitlint**: Conventional Commits format -### Conventional Commits Format - -``` -[optional scope]: -``` - -Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`, `ci`, `revert` -Header max length: 100 characters. +Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`, `ci`, `revert`. Max 100 chars. --- ## OCPP Spec Search (QMD) -Collection `ocpp-specs` — OCPP 1.6, 2.0.1, 2.1 specs from `docs/` (24 files, 3213 chunks). - -**Project-specific gotchas**: - -- `CI=true` disables LLM ops → prefix `env -u CI` on all `qmd query` / `qmd vsearch` calls. `qmd search` (BM25 only) works without it. -- Collection flag: `-c` or `--collection` (singular). -- Result limit flag: `-n`. +Collection `ocpp-specs` — OCPP 1.6, 2.0.1, 2.1 specs from `docs/`. -Re-index after spec updates: `qmd update --pull && qmd embed` +- `CI=true` disables LLM ops → prefix `env -u CI` on `qmd query` / `qmd vsearch` +- `qmd search` (BM25 only) works without it +- Re-index: `qmd update --pull && qmd embed` --- @@ -149,6 +170,6 @@ Re-index after spec updates: `qmd update --pull && qmd embed` ```bash cd docker make # Build + start simulator + web UI containers -make clean # Stop containers + remove images +make clean # Stop + remove make docker-push-ecr # Build, tag, push to AWS ECR ``` diff --git a/.serena/memories/task_completion_checklist.md b/.serena/memories/task_completion_checklist.md index ad4188a3..8bea104c 100644 --- a/.serena/memories/task_completion_checklist.md +++ b/.serena/memories/task_completion_checklist.md @@ -1,46 +1,45 @@ # Task Completion Checklist -## After Completing Any Task - -### 1. Root Simulator (always) - -```bash -pnpm format # prettier + eslint auto-fix -pnpm typecheck # tsc --noEmit -pnpm lint # eslint check only -pnpm build # esbuild production bundle -pnpm test # node native test runner -``` - -### 2. Web UI (if `ui/web/` files changed) - -```bash -cd ui/web -pnpm format # prettier + eslint auto-fix -pnpm typecheck # vue-tsc --noEmit -pnpm lint # eslint check only -pnpm build # vite production build -pnpm test # vitest -``` - -### 3. OCPP Mock Server (if `tests/ocpp-server/` files changed) - -```bash -cd tests/ocpp-server -poetry run task format # ruff check --fix + ruff format -poetry run task typecheck # mypy -poetry run task lint # ruff check --diff + ruff format --check -poetry run task test # pytest -v -``` - -### 4. Documentation - -- Update docs if public API changed +Run quality gates for each sub-project affected by your changes. See `suggested_commands` for full command reference. + +## Quality Gate Order + +For each sub-project: `pnpm format` → `pnpm typecheck` → `pnpm lint` → `pnpm build` (if applicable) → `pnpm test` + +### 1. Root Simulator (if `src/` or `tests/` changed) + +`pnpm format && pnpm typecheck && pnpm lint && pnpm build && pnpm test` + +### 2. UI Common (if `ui/common/` changed) + +`cd ui/common && pnpm format && pnpm typecheck && pnpm lint && pnpm test` + +Note: `pnpm build` is identical to `pnpm typecheck` (source-only package, no build artifacts). + +### 3. CLI (if `ui/cli/` changed) + +`cd ui/cli && pnpm format && pnpm typecheck && pnpm lint && pnpm build && pnpm test` + +### 4. Web UI (if `ui/web/` changed) + +`cd ui/web && pnpm format && pnpm typecheck && pnpm lint && pnpm build && pnpm test:coverage` + +Note: Use `test:coverage` (single-run). `pnpm test` starts Vitest in watch mode locally. + +### 5. OCPP Mock Server (if `tests/ocpp-server/` changed) + +`cd tests/ocpp-server && poetry run task format && poetry run task typecheck && poetry run task lint && poetry run task test` + +### 6. Documentation + +- Update relevant README if user-facing behavior changed (root `README.md`, `ui/cli/README.md`, `ui/web/README.md`) - Commit messages follow Conventional Commits (enforced by hook) -### 5. OCPP Compliance (if applicable) +### 7. OCPP Compliance (if applicable) -- Verify OCPP standard compliance for any protocol changes +- Verify OCPP standard compliance for protocol changes - Validate against JSON schemas when `ocppStrictCompliance` is enabled -Refer to `code_style_conventions` memory for coding rules, and `suggested_commands` memory for full command reference. +### Dependency Order + +If changing `ui/common`: run common gates first, then rebuild/test CLI and Web UI (they depend on it). -- 2.43.0