90d6a73a60
Tasks 1.1-1.9 marked done with their landing commit SHAs. Tasks 1.10 (observability), 1.12 (production hardening), and 1.13 (device authority) marked paused with explicit resume triggers — pilot deployment on real Teltonika hardware takes priority. Task 1.11 remains as next, in slimmed form for the pilot (no /readyz healthcheck since the metrics endpoint is part of paused 1.10).
58 lines
4.0 KiB
Markdown
58 lines
4.0 KiB
Markdown
# Task 1.1 — Project scaffold
|
|
|
|
**Phase:** 1 — Inbound telemetry
|
|
**Status:** 🟩 Done — landed in commit `1e9219d`
|
|
**Depends on:** None
|
|
**Wiki refs:** `docs/wiki/sources/teltonika-ingestion-architecture.md` § Project location and layout
|
|
|
|
## Goal
|
|
|
|
Initialize the Node.js / TypeScript project with the directory layout from the wiki, install the agreed tooling, and produce a "hello world" `main.ts` that the rest of Phase 1 builds on.
|
|
|
|
## Deliverables
|
|
|
|
- `package.json` declaring:
|
|
- Type: `"module"` (ESM only).
|
|
- Engines: `"node": ">=22"`.
|
|
- Scripts: `build`, `dev`, `start`, `test`, `test:watch`, `lint`, `format`, `typecheck`.
|
|
- Dependencies (production): `ioredis`, `pino`, `pino-pretty` (dev-only via NODE_ENV check), `prom-client`, `zod`.
|
|
- Dev dependencies: `typescript`, `@types/node`, `vitest`, `@vitest/coverage-v8`, `eslint`, `@typescript-eslint/parser`, `@typescript-eslint/eslint-plugin`, `prettier`, `tsx` (for `dev` watch).
|
|
- `tsconfig.json` with `strict: true`, `target: ES2022`, `module: NodeNext`, `moduleResolution: NodeNext`, `outDir: dist`, `rootDir: src`, `declaration: false`, `noUncheckedIndexedAccess: true`.
|
|
- `eslint.config.js` (flat config) with `@typescript-eslint/recommended-type-checked` plus a small project-specific allow-list.
|
|
- `.prettierrc` — 2 spaces, single quotes, no semis at line end OR keep semis (pick one and stay consistent — recommend keep semis to match Node convention).
|
|
- `.gitignore` — `node_modules/`, `dist/`, `coverage/`, `.env`, `.env.local`, `*.log`.
|
|
- `.dockerignore` — same as `.gitignore` plus `.git/`, `.planning/`, `test/`, `*.md` except `README.md`.
|
|
- Empty directories with `.gitkeep` files where Phase 1 will fill them in:
|
|
- `src/core/`, `src/adapters/teltonika/codec/data/`, `src/adapters/teltonika/codec/command/`, `src/config/`, `src/observability/`
|
|
- `test/fixtures/teltonika/codec8/`, `test/fixtures/teltonika/codec8e/`, `test/fixtures/teltonika/codec16/`
|
|
- `src/main.ts` — minimal stub: imports a logger (placeholder until task 1.3), prints "tcp-ingestion starting" and exits with code 0.
|
|
- `README.md` — short description pointing at `.planning/ROADMAP.md` for the work plan, and at `../docs/wiki/` for the architectural specification.
|
|
|
|
## Specification
|
|
|
|
- **Package manager:** pnpm. Commit `pnpm-lock.yaml`. The Dockerfile in task 1.11 will use `pnpm fetch` for layer-cache friendliness.
|
|
- **Module style:** ESM throughout. No CJS interop hacks. All files use `import`/`export` and `.js` suffix on relative imports per Node ESM resolution rules.
|
|
- **TypeScript path style:** Use relative imports for now. No `paths` aliases — they add a bundler dependency at runtime that we don't want.
|
|
- **No bundler.** The build is `tsc` only. Runtime is plain Node consuming `dist/`. The Dockerfile will copy `dist/` and `node_modules/`.
|
|
- **Linting style:** Configure ESLint to enforce `@typescript-eslint/no-floating-promises` and `@typescript-eslint/no-misused-promises` — both are critical in a TCP server where unhandled promise rejections will silently lose work.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [ ] `pnpm install` succeeds with no warnings other than peer deps.
|
|
- [ ] `pnpm typecheck` succeeds on the empty project.
|
|
- [ ] `pnpm lint` succeeds.
|
|
- [ ] `pnpm build` produces `dist/main.js`.
|
|
- [ ] `pnpm start` runs the compiled output and prints the startup message.
|
|
- [ ] `pnpm test` runs (with no tests) and exits successfully.
|
|
- [ ] `pnpm dev` runs `main.ts` via `tsx` and prints the startup message.
|
|
- [ ] Repository builds reproducibly: deleting `node_modules` and `dist`, then `pnpm install --frozen-lockfile && pnpm build` produces identical output.
|
|
|
|
## Risks / open questions
|
|
|
|
- Pinning Node 22 LTS vs 20 LTS: 22 is current LTS in 2026 and has stable native fetch + better worker thread perf. Stay with 22 unless deployment infra forces 20.
|
|
- ESLint v9 flat config: ensure the version is compatible with `@typescript-eslint/*` v8+. If issues arise, fall back to legacy `.eslintrc.json` until upstream catches up.
|
|
|
|
## Done
|
|
|
|
(Fill in once complete: commit SHA, brief notes.)
|