Commit Graph

5 Commits

Author SHA1 Message Date
mAi
1ea6082948 feat: db store — IO markers CRUD, snapshot wiring
Schema already in 001_init.sql; this is just the Go store layer.

IO markers are project-scoped wall-outlet terminators (a cable's
"this end plugs into a wall socket outside the diagram" endpoint).
Power-by-convention; no schema-level type enforcement.

- CreateIOMarker validates frame_id is in the same project (cross-project
  ref → ErrInvalidInput), defaults label to "IO" when blank.
- GetIOMarker is project-scoped — wrong-project read returns ErrNotFound.
- UpdateIOMarker uses the FrameRef tri-state for frame_id (same as
  DeviceUpdate) so callers can clear it explicitly.
- DeleteIOMarker is direct delete — ON DELETE SET NULL from the schema
  drops the io_markers.frame_id ref cleanly when the frame is deleted
  (verified by TestDeleteFrame_SetsIOMarkerFrameIDToNull).

Snapshot now populates IOMarkers from the store; field type tightened
from []any to []IOMarker.

7 new table-driven tests, all green with -race.
2026-05-16 00:05:40 +02:00
mAi
cf1671e8c1 feat: db store — frames + devices CRUD, project-scoped
Snapshot now populates frames + devices from the DB (slice 1 left them as
empty arrays).

Frame store:
- CreateFrame requires positive width/height; rejects empty name; UNIQUE
  (project_id, name) collisions surface as ErrConflict via mapWriteErr.
- GetFrame is project-scoped — wrong-project read returns ErrNotFound.
- UpdateFrame applies a partial; project_id is not exposed (moving a
  frame across projects would orphan its devices).
- DeleteFrame relies on the schema's ON DELETE SET NULL to drop
  devices' frame_id refs cleanly; verified by test.

Device store:
- CreateDevice defaults color to #1e1e1e if blank; rejects empty name,
  non-positive size; validates frame_id is in the same project (returns
  ErrInvalidInput on cross-project ref).
- UpdateDevice uses a FrameRef tri-state for frame_id so callers can
  distinguish "leave alone" from "clear to NULL" from "move to frame X".
- Cross-project frame_id on PATCH is rejected with ErrInvalidInput.
- ListDevices supports an optional frame_id filter.

13 new table-driven tests, all green with -race.
2026-05-15 18:16:33 +02:00
mAi
905c75c6db test+docs: store coverage + README for slice 1
Adds table-driven store tests:
- projects: drawing_name auto-default, explicit-name accept, empty-name
  reject, duplicate-name conflict, ordered list, GetProject not-found,
  partial PATCH semantics, blank-drawing-name re-default on PATCH,
  ?confirm=<name> guardrail (wrong / empty / correct), snapshot returns
  the 5 globally-seeded cable_types
- cable_types: 5 seeded with the legend colours, global UNIQUE(name),
  rename + recolour, RESTRICT-blocked delete when a cable references the
  type (with count surfaced via CountCablesUsingType), unused delete
  succeeds, project deletion does NOT cascade into cable_types

go test -race ./... passes. Updates README.md with run instructions,
env vars, the slice-1 API surface, and the slice roadmap.
2026-05-15 16:48:29 +02:00
mAi
255d52e7c4 feat: db store — projects + cable_types CRUD with sentinel errors and confirm-name guardrail 2026-05-15 16:45:29 +02:00
mAi
cd34dde133 feat: db migrations runner + 001_init.sql (full v3 schema, 5 cable_types seeded) 2026-05-15 16:45:29 +02:00