Files
spotlightcam/docs/archive/ADMIN_CLI.md
Radosław Gierwiało 975d258497 docs: reorganize documentation structure for better context efficiency
Reorganization changes:
1. Moved from root → docs/:
   - QUICKSTART.md
   - QUICK_TEST.md
   - WEBRTC_TESTING_GUIDE.md

2. Created docs/archive/ and moved archival files:
   - COMPLETED.md (completed tasks archive)
   - PHASE_1.5.md (historical phase documentation)
   - RESOURCES.md (learning resources)
   - SECURITY_AUDIT.md (security audit)
   - ADMIN_CLI.md (CLI documentation)

3. Updated all references in:
   - README.md
   - docs/CONTEXT.md
   - docs/TODO.md
   - docs/SESSION_CONTEXT.md
   - docs/DEPLOYMENT.md
   - docs/QUICK_TEST.md

Active docs/ now contains only essential files:
- SESSION_CONTEXT.md (primary for context restoration)
- TODO.md
- CONTEXT.md
- ARCHITECTURE.md
- DEPLOYMENT.md
- MONITORING.md
- QUICKSTART.md
- QUICK_TEST.md
- WEBRTC_TESTING_GUIDE.md

Benefits:
- Reduced token usage when reading docs/ for context
- Clear separation between active and archived documentation
- Better organization for future maintenance
2025-11-20 22:42:06 +01:00

6.9 KiB
Raw Permalink Blame History

Admin CLI & REPL — spotlight.cam

Administrative console for maintenance tasks inside the backend container. Provides both oneshot commands and an interactive REPL with app context.


Quick Start

  • Development REPL: docker compose exec backend npm run cli
  • Production REPL: docker compose exec backend-prod npm run cli
  • One-shot examples:
    • docker compose exec backend npm run cli -- users:list --limit 20
    • docker compose exec backend npm run cli -- events:checkin --username john_doe --slug warsaw-dance-2025

With Makefile shortcuts:

  • make dev-cli / make prod-cli
  • make dev-up, make dev-down, make prod-up, make prod-down, rebuild variants also available

REPL Features

  • Default entry: running npm run cli starts a Node.js REPL with:
    • prisma client and bcrypt in context
    • Aliases: u = prisma.user, e = prisma.event, m = prisma.match, ep = prisma.eventParticipant, r = prisma.rating
    • Toplevel await: await u.findMany({ take: 5 })
    • Autocomplete (TAB) from Node REPL
    • Persistent history in .repl_history (besteffort)
  • Run CLI subcommands from inside REPL:
    • .cli users:list --limit 20
    • run('events:checkin --username john_doe --slug warsaw-dance-2025')
  • Error handling: CLI errors (e.g., missing flags) do not exit the REPL; the error is printed and you can correct the command and retry.

Commands

Cheatsheet

  • repl
  • users:list [--limit <n>]
  • users:create --email <e> --username <u> --password <p> [--first <f>] [--last <l>]
  • users:verify --email <e>
  • events:list [--limit <n>]
  • events:details --slug <slug>
  • events:participants --slug <slug> [--limit <n>] [--csv]
  • events:import:wsdc [--dry-run] [--since YYYY-MM-DD] [--until YYYY-MM-DD] [--limit <n>]
  • matches:list [--limit <n>] [--status pending|accepted|completed]
  • events:checkin --username <u> --slug <s>
  • logs:app [--lines <n>]
  • logs:messages [--limit <n>]

users:list

  • Description: List users
  • Options:
    • --limit <n>: number of rows (default: 50)
  • Examples:
    • CLI: npm run cli -- users:list --limit 20
    • REPL: .cli users:list --limit 20

users:create

  • Description: Create a user
  • Required:
    • --email <email>
    • --username <username>
    • --password <password> (hashed with bcrypt)
  • Optional:
    • --first <firstName>
    • --last <lastName>
  • Examples:
    • CLI: npm run cli -- users:create --email admin@example.com --username admin --password 'Secret123!'
    • REPL: run("users:create --email a@b.c --username admin --password 'Secret123!'")

users:verify

  • Description: Mark user email as verified and clear verification fields
  • Required:
    • --email <email>
  • Example: npm run cli -- users:verify --email admin@example.com

events:list

  • Description: List events
  • Options:
    • --limit <n> (default: 50)
  • Example: npm run cli -- events:list --limit 10

events:details

  • Description: Show details for a specific event by slug
  • Required:
    • --slug <event-slug>
  • Options:
    • --participants <n>: number of recent participants to show (default: 10)
  • Output: basic fields (id, slug, name, start/end, location, worldsdcId), participantsCount, optional check-in token, relation counts, event chat room id and message count, and up to N recent participants
  • Examples:
    • npm run cli -- events:details --slug warsaw-dance-2025
    • npm run cli -- events:details --slug warsaw-dance-2025 --participants 25

matches:list

  • Description: List matches
  • Options:
    • --limit <n> (default: 50)
    • --status <pending|accepted|completed> filter
  • Example: npm run cli -- matches:list --status accepted --limit 20

events:checkin

  • Description: Attach user to event by username and event slug (simulate QR check-in)
  • Required:
    • --username <username>
    • --slug <event-slug>
  • Behavior: Upserts into event_participants (idempotent)
  • Example: npm run cli -- events:checkin --username john_doe --slug warsaw-dance-2025

events:participants

  • Description: List participants for an event by slug
  • Required:
    • --slug <event-slug>
  • Options:
    • --limit <n>: number of rows (default: 100)
    • --csv: output as CSV (stdout)
  • Output: eventId, slug, userId, username, email, firstName, lastName, country, city, joinedAt
  • Examples:
    • npm run cli -- events:participants --slug warsaw-dance-2025 --limit 50
    • npm run cli -- events:participants --slug warsaw-dance-2025 --limit 200 --csv > participants.csv

events:import:wsdc

  • Description: Import events from worldsdc.com.
  • Sources:
    • --source list: parse Event List page (includes Event Location + Country)
    • --source calendar: parse Events Calendar page (title/start/end/url)
    • --source auto (default): try calendar first, then list if calendar parsing yields no events
  • Options:
    • --dry-run: show what would be created without writing to DB
    • --since YYYY-MM-DD: only events on/after date
    • --until YYYY-MM-DD: only events on/before date
    • --limit <n>: limit considered items after filtering
    • --update-missing-location: when an event already exists and its location is empty/"Unknown", update it from the imported source (list recommended)
  • Examples:
    • npm run cli -- events:import:wsdc --dry-run --since 2024-01-01 --until 2024-12-31
    • npm run cli -- events:import:wsdc --source list --limit 50
    • npm run cli -- events:import:wsdc --source list --update-missing-location
  • Field mapping: name, startDate, endDate, sourceUrl, location (from list) or Unknown (from calendar). No updates to participantsCount.
  • Dedup strategy: skip when (name, startDate) already exists.
  • Alias: events:import:worldsdc (kept for backwards compatibility).

logs:app

  • Description: Tail application log file (if configured)
  • Options:
    • --lines <n> number of lines from end (default: 200)
  • Env:
    • LOG_FILE — absolute/relative path inside backend container (default: ./app.log in working dir)
  • Note: For container logs prefer docker compose logs -f backend

logs:messages

  • Description: Recent chat messages from DB
  • Options:
    • --limit <n> (default: 50)
  • Output: message id, time, user, room (event/private), type, first 100 chars

Troubleshooting

  • REPL not interactive: ensure TTY: docker compose exec -it backend npm run cli
  • DB access errors: verify backend container env and DB service are running
  • events:checkin says not found: confirm username and slug exist in DB
  • Autocomplete: works with Node REPL; press TAB after prisma. to see model methods

Security Notes

  • CLI has full DB access; restrict usage to SSH + container exec
  • Do not expose CLI via HTTP endpoints
  • Consider audit logs for sensitive actions if needed

Domain Notes

  • In spotlight.cam, participantsCount reflects local checkins (EventParticipants), not official WSDC participant metrics.
  • The WSDC calendar source does not provide reliable location or participant counts; importer intentionally does not set worldsdcId or participantsCount.