Files
CableGUI/internal/db/db.go
mAi c206a331ec rename: mCables → CableGUI (project + repo + image + paths)
Full project rename per m's call. Single atomic commit because the
codebase rename is a coupled change — go module path, env vars, DB
default, Docker artefact names, and on-disk mDock paths all flip
together.

- go.mod: module mgit.msbls.de/m/mcables → mgit.msbls.de/m/cablegui
- cmd/mcables → cmd/cablegui (git mv)
- All Go imports rewritten to the new module path
- Env vars: MCABLES_ADDR/MCABLES_DB → CABLEGUI_ADDR/CABLEGUI_DB
- DB default path: data/mcables.db → data/cablegui.db
- Dockerfile + docker-compose.yml: image, container_name, env vars,
  bind-mount /home/m/stacks/mcables → /home/m/stacks/cablegui,
  secrets /home/m/secrets/mcables → /home/m/secrets/cablegui
- Makefile: bin target + run/build commands point at cmd/cablegui
- .gitignore + .dockerignore: /mcables → /cablegui
- README, docs/design.md, CLAUDE.md: prose + paths + image name
- web/static/index.html: <title> + brand
- web/static/main.js + web/web.go: header comment
- internal/exporter: Scene.Source "mcables" → "cablegui"
- internal/server/export.go: error-detail secrets path
- internal/db/migrations/*.sql: header comments (mCables vN → CableGUI vN)

Memory group_id kept as "mcables" to preserve existing memory continuity.
Documented as historical in CLAUDE.md.

go build ./... clean; go test -race ./... green
2026-05-16 15:35:42 +02:00

48 lines
1.4 KiB
Go

// Package db owns SQLite access for CableGUI: migrations runner + the
// query layer (store.go). The Store wraps a *sql.DB with helpers; tests
// and the HTTP layer take a *Store, never a raw *sql.DB.
package db
import (
"database/sql"
"fmt"
_ "modernc.org/sqlite"
)
// Open opens (or creates) the SQLite file at path and returns a Store
// with WAL + foreign keys + busy_timeout configured.
func Open(path string) (*Store, error) {
// `_pragma` query params are honoured by modernc.org/sqlite for
// connection-time PRAGMA setup. journal_mode WAL is persistent
// across opens; the others apply per-connection.
dsn := fmt.Sprintf(
"file:%s?_pragma=journal_mode(WAL)&_pragma=foreign_keys(ON)&_pragma=busy_timeout(5000)",
path,
)
d, err := sql.Open("sqlite", dsn)
if err != nil {
return nil, fmt.Errorf("open sqlite: %w", err)
}
if err := d.Ping(); err != nil {
_ = d.Close()
return nil, fmt.Errorf("ping sqlite: %w", err)
}
// Single writer keeps things deterministic for a local-LAN tool;
// reads scale fine in WAL.
d.SetMaxOpenConns(1)
return &Store{db: d}, nil
}
// Store is the application's handle on the SQLite database.
type Store struct {
db *sql.DB
}
// DB returns the underlying *sql.DB. Used by Migrate and (sparingly) by
// callers that need a raw query escape hatch.
func (s *Store) DB() *sql.DB { return s.db }
// Close releases the database.
func (s *Store) Close() error { return s.db.Close() }