From d1ef9800f1e527f989f27492dabd6ceb0701bd9d Mon Sep 17 00:00:00 2001 From: Sebastian Frank Date: Fri, 27 Feb 2026 13:29:44 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20fix:=20enhance=20watch=20mode=20?= =?UTF-8?q?to=20reload=20browser=20on=20build=20completion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/skills/live-mongodb/SKILL.md | 175 +++++++++++++++++++++++++++ scripts/esbuild-wrapper.js | 6 +- 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 .agents/skills/live-mongodb/SKILL.md diff --git a/.agents/skills/live-mongodb/SKILL.md b/.agents/skills/live-mongodb/SKILL.md new file mode 100644 index 0000000..7ed26cf --- /dev/null +++ b/.agents/skills/live-mongodb/SKILL.md @@ -0,0 +1,175 @@ +--- +name: live-mongodb +description: Connect to the live (production) MongoDB via chisel tunnel and perform read/write operations. Use this skill when you need to inspect or update live data directly in the production database. +--- + +# Live MongoDB Access via Chisel Tunnel + +## Overview + +Die Produktions-MongoDB läuft auf dem Server aus `PRODUCTION_SERVER` in `.env`. Der Zugang erfolgt über einen **Chisel-Tunnel**, der den Remote-MongoDB-Port auf localhost mapped. Damit kann man dann entweder über `mongosh`, `mongodump`/`mongorestore`, oder den **MongoDB MCP Server** auf die Live-Daten zugreifen. + +## Umgebungsvariablen (aus .env) + +| Variable | Beschreibung | +| ------------------------ | ----------------------------------------------- | +| `PRODUCTION_SERVER` | Produktionsserver (z.B. `dock4.basehosts.de`) | +| `PRODUCTION_TIBI_PREFIX` | DB-Prefix auf Produktion (z.B. `wmbasic`) | +| `TIBI_NAMESPACE` | Projekt-Namespace | +| **Live DB Name** | = `${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}` | +| Chisel-Port (Remote) | `10987` — Chisel-Server auf dem Produktionshost | + +## Schritt 1: Chisel-Tunnel starten + +Das Chisel-Passwort muss vom User bereitgestellt werden. Tunnel starten: + +```bash +# Passwort vom User erfragen oder aus Umgebung nehmen +read -s -p "Chisel-Passwort: " CHISEL_PASSWORD + +# Tunnel starten (mappt remote mongo:27017 → localhost:27017) +chisel client --auth "coder:${CHISEL_PASSWORD}" \ + http://${PRODUCTION_SERVER}:10987 \ + 27017:mongo:27017 & + +# Kurz warten, bis der Tunnel steht +sleep 3 +``` + +**WICHTIG:** Der lokale Docker-Mongo-Container muss gestoppt sein oder auf einem anderen Port laufen, da der Tunnel Port 27017 lokal belegt. Falls der lokale Container läuft: + +```bash +# Lokales MongoDB stoppen (belegt sonst Port 27017) +docker compose -f docker-compose-local.yml stop mongo +``` + +Alternativ kann der Tunnel auf einen anderen lokalen Port gemappt werden: + +```bash +chisel client --auth "coder:${CHISEL_PASSWORD}" \ + http://${PRODUCTION_SERVER}:10987 \ + 37017:mongo:27017 & +# → erreichbar unter mongodb://localhost:37017/${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE} +``` + +## Schritt 2: Verbinden + +### Option A: mongosh (interaktiv) + +```bash +mongosh "mongodb://localhost:27017/${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}" +``` + +### Option B: MongoDB MCP Server (für Copilot) + +Den MongoDB MCP über die Umgebungsvariable `MDB_MCP_CONNECTION_STRING` auf die Live-DB umleiten. + +**Temporär für eine Session** – in `.vscode/mcp.json` eine zweite Server-Config eintragen: + +```jsonc +{ + "servers": { + "mongodb-live": { + "command": "npx", + "args": ["-y", "mongodb-mcp-server@latest"], + "type": "stdio", + "env": { + "MDB_MCP_CONNECTION_STRING": "mongodb://localhost:27017/${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}", + "MDB_MCP_READ_ONLY": "false", + "MDB_MCP_TELEMETRY": "disabled", + }, + }, + }, +} +``` + +> **Achtung:** `MDB_MCP_READ_ONLY=false` erlaubt Schreiboperationen! Nach getaner Arbeit den Server wieder entfernen oder auf `true` setzen. + +### Option C: Einmalige Kommandos via Terminal + +```bash +DB_NAME="${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}" + +# Dokument suchen +mongosh "mongodb://localhost:27017/$DB_NAME" \ + --eval 'db.content.findOne({path: "/"})' + +# Feld updaten +mongosh "mongodb://localhost:27017/$DB_NAME" \ + --eval 'db.content.updateOne({path: "/"}, {$set: {"title": "Neuer Titel"}})' +``` + +## Schritt 3: Tunnel beenden + +```bash +killall chisel +``` + +Falls der lokale Mongo-Container vorher gestoppt wurde, wieder starten: + +```bash +docker compose -f docker-compose-local.yml start mongo +``` + +## Sicherheitsregeln + +1. **Immer zuerst lesen, dann schreiben.** Vor jedem Update das betroffene Dokument mit `find`/`findOne` inspizieren. +2. **Backup vor Bulk-Updates.** Bei Massenänderungen vorher ein `mongodump` machen: + ```bash + mongodump --uri="mongodb://localhost:27017" \ + --db=${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE} \ + --collection= \ + --gzip --archive=backup--$(date +%Y%m%d-%H%M%S).gz + ``` +3. **User muss Chisel-Passwort liefern.** Das Passwort niemals hardcoden oder in Dateien speichern. +4. **Updates immer bestätigen lassen.** Vor jeder Schreiboperation dem User die geplante Query zeigen und explizit nach Bestätigung fragen. +5. **Nach getaner Arbeit Tunnel schließen** und ggf. `mongodb-live` MCP-Server aus der Config entfernen. +6. **Kein Drop/Delete von Collections** ohne explizite User-Anweisung. +7. **SSR-Cache leeren nach Datenänderungen.** Wenn Daten in Collections geändert werden, die auf der Website gerendert werden (z.B. `content`, `navigation`), muss der SSR-Cache invalidiert werden, damit die Änderungen sichtbar werden. Dazu die `ssr`-Collection leeren: + ```bash + mongosh "mongodb://localhost:27017/$DB_NAME" \ + --eval 'db.ssr.deleteMany({})' + ``` + Siehe auch den Skill `tibi-ssr-caching` für Details zur Cache-Invalidierung über die API. + +## Wichtige Collections + +| Collection | Beschreibung | +| ------------ | ------------------------------- | +| `content` | CMS-Inhaltsseiten (Pagebuilder) | +| `navigation` | Navigationsstruktur | +| `medialib` | Medien-Bibliothek | +| `ssr` | SSR-Cache | + +> Weitere Collections je nach Projekt — siehe `api/collections/` für die aktuelle Liste. + +## Typische Anwendungsfälle + +### Content-Eintrag inspizieren + +```js +db.content.findOne({ path: "/" }) +``` + +### Navigation aktualisieren + +```js +db.navigation.updateOne({ type: "header", language: "de" }, { $set: { "items.0.label": "Neues Label" } }) +``` + +### Dokument-Struktur inspizieren + +```js +// Schema einer Collection anschauen +db.content.findOne() + +// Alle Felder eines Dokuments auflisten +Object.keys(db.content.findOne()) +``` + +## Fehlerbehebung + +- **"Connection refused" auf Port 27017:** Chisel-Tunnel läuft nicht oder lokaler Mongo blockiert den Port. Prüfen mit `ss -tlnp | grep 27017`. +- **"Authentication failed":** Chisel-Passwort falsch. User erneut fragen. +- **Langsame Queries:** Produktions-DB kann große Collections haben. Immer mit Filtern arbeiten, nie `find({})` ohne Limit. +- **Rate Limiting:** Kein Thema bei direktem DB-Zugang (nur bei API-Calls relevant). diff --git a/scripts/esbuild-wrapper.js b/scripts/esbuild-wrapper.js index 44ce0aa..cd5f997 100644 --- a/scripts/esbuild-wrapper.js +++ b/scripts/esbuild-wrapper.js @@ -56,7 +56,11 @@ switch (process.argv?.length > 2 ? process.argv[2] : "build") { bs.init(config.browserSync) case "watch": // config.options.incremental = true - build(true) + build(true).then(() => { + if (bs) { + bs.reload() + } + }) const watcher = watch(config.watch.path) log("watching files...") watcher.on("change", function (path) {