c8a5f4cd68
ROADMAP plus granular task files per phase. Phase 1 (12 tasks + 1.13 device authority) covers Codec 8/8E/16 telemetry ingestion; Phase 2 (6 tasks) covers Codec 12/14 outbound commands; Phase 3 enumerates deferred items.
4.0 KiB
4.0 KiB
Task 1.1 — Project scaffold
Phase: 1 — Inbound telemetry
Status: ⬜ Not started
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.jsondeclaring:- 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(fordevwatch).
- Type:
tsconfig.jsonwithstrict: 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-checkedplus 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.gitignoreplus.git/,.planning/,test/,*.mdexceptREADME.md.- Empty directories with
.gitkeepfiles 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.mdfor 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 usepnpm fetchfor layer-cache friendliness. - Module style: ESM throughout. No CJS interop hacks. All files use
import/exportand.jssuffix on relative imports per Node ESM resolution rules. - TypeScript path style: Use relative imports for now. No
pathsaliases — they add a bundler dependency at runtime that we don't want. - No bundler. The build is
tsconly. Runtime is plain Node consumingdist/. The Dockerfile will copydist/andnode_modules/. - Linting style: Configure ESLint to enforce
@typescript-eslint/no-floating-promisesand@typescript-eslint/no-misused-promises— both are critical in a TCP server where unhandled promise rejections will silently lose work.
Acceptance criteria
pnpm installsucceeds with no warnings other than peer deps.pnpm typechecksucceeds on the empty project.pnpm lintsucceeds.pnpm buildproducesdist/main.js.pnpm startruns the compiled output and prints the startup message.pnpm testruns (with no tests) and exits successfully.pnpm devrunsmain.tsviatsxand prints the startup message.- Repository builds reproducibly: deleting
node_modulesanddist, thenpnpm install --frozen-lockfile && pnpm buildproduces 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.jsonuntil upstream catches up.
Done
(Fill in once complete: commit SHA, brief notes.)