feat: automatische Content-Pipeline (release → pairs → übersetzen → audio → ready)
- pictures.pipeline_* Spalten + app_settings Tabelle (Migration) - lib/placeholders.js: Placeholder-Auflösung; TTS spricht keine UUIDs mehr - lib/pairContent.js: geteilte Pair-Logik (Readiness mit Skip-Optionen) - lib/generatePairs.js: Claude-Generierung (konfigurierbare Anzahl, nur Nomen/Adjektive bei word-Pairs) + serverseitige Persistenz inkl. object_pairs - lib/pipeline.js: In-Process-Runner, idempotente Schritte, Boot-Resume - routes/pipeline.js: release/retry/overview/bundle/settings + Bild-Publish (kaskadiert Fragen/Statements/Pairs/Wörter/Objekte/Bild) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -603,6 +603,38 @@ async function migrate() {
|
||||
ON CONFLICT (language) DO NOTHING
|
||||
`).catch(() => {});
|
||||
|
||||
// ── Content-Pipeline: Job-Tracking direkt auf der Picture-Zeile ──────────────
|
||||
await query(`ALTER TABLE pictures ADD COLUMN IF NOT EXISTS pipeline_status TEXT NOT NULL DEFAULT 'none'`).catch(() => {});
|
||||
await query(`ALTER TABLE pictures DROP CONSTRAINT IF EXISTS pictures_pipeline_status_check`).catch(() => {});
|
||||
await query(`
|
||||
ALTER TABLE pictures ADD CONSTRAINT pictures_pipeline_status_check
|
||||
CHECK (pipeline_status IN ('none', 'queued', 'running', 'failed', 'ready', 'published'))
|
||||
`).catch(() => {});
|
||||
await query(`ALTER TABLE pictures ADD COLUMN IF NOT EXISTS pipeline_step TEXT`).catch(() => {});
|
||||
await query(`ALTER TABLE pictures ADD COLUMN IF NOT EXISTS pipeline_progress JSONB`).catch(() => {});
|
||||
await query(`ALTER TABLE pictures ADD COLUMN IF NOT EXISTS pipeline_error TEXT`).catch(() => {});
|
||||
await query(`ALTER TABLE pictures ADD COLUMN IF NOT EXISTS pipeline_started_at TIMESTAMPTZ`).catch(() => {});
|
||||
await query(`ALTER TABLE pictures ADD COLUMN IF NOT EXISTS pipeline_finished_at TIMESTAMPTZ`).catch(() => {});
|
||||
|
||||
// app_settings — generischer Key/Value-Store (JSONB) für Konfiguration
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS app_settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value JSONB NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`);
|
||||
await query(`
|
||||
DROP TRIGGER IF EXISTS app_settings_updated_at ON app_settings;
|
||||
CREATE TRIGGER app_settings_updated_at
|
||||
BEFORE UPDATE ON app_settings
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at()
|
||||
`);
|
||||
await query(`
|
||||
INSERT INTO app_settings (key, value) VALUES ('pipeline.pairs_per_object', '5'::jsonb)
|
||||
ON CONFLICT (key) DO NOTHING
|
||||
`).catch(() => {});
|
||||
|
||||
// ── Migrate old {{uuid}} placeholders → new {{label.w:uuid}} / {{label.o:uuid}} ──
|
||||
await migratePlaceholders();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user