add version badge in nav, apply path mappings at execution time, clear done/error jobs
All checks were successful
Build and Push Docker Image / build (push) Successful in 58s
All checks were successful
Build and Push Docker Image / build (push) Successful in 58s
- show version (from package.json) in nav bar, warn on frontend/server mismatch - apply path_mappings to file access check and command string at execution time so existing scans with old jellyfin paths work without re-scanning - add clear done/errors button on execute page - bump version to 2026.03.04 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Hono } from 'hono';
|
||||
import { stream } from 'hono/streaming';
|
||||
import { getDb } from '../db/index';
|
||||
import { getDb, applyPathMappings, applyPathMappingsToCommand } from '../db/index';
|
||||
import { execStream } from '../services/ssh';
|
||||
import type { Job, Node, MediaItem, MediaStream } from '../types';
|
||||
import { predictExtractedFiles } from '../services/ffmpeg';
|
||||
@@ -129,6 +129,12 @@ app.post('/clear', (c) => {
|
||||
return c.json({ ok: true, cleared: result.changes });
|
||||
});
|
||||
|
||||
app.post('/clear-completed', (c) => {
|
||||
const db = getDb();
|
||||
const result = db.prepare("DELETE FROM jobs WHERE status IN ('done', 'error')").run();
|
||||
return c.json({ ok: true, cleared: result.changes });
|
||||
});
|
||||
|
||||
// ─── SSE ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
app.get('/events', (c) => {
|
||||
@@ -167,8 +173,9 @@ async function runJob(job: Job): Promise<void> {
|
||||
if (!job.node_id) {
|
||||
const itemRow = db.prepare('SELECT file_path FROM media_items WHERE id = ?').get(job.item_id) as { file_path: string } | undefined;
|
||||
if (itemRow?.file_path) {
|
||||
try { accessSync(itemRow.file_path, constants.R_OK | constants.W_OK); } catch (fsErr) {
|
||||
const msg = `File not accessible: ${itemRow.file_path}\n${(fsErr as Error).message}`;
|
||||
const mappedPath = applyPathMappings(itemRow.file_path);
|
||||
try { accessSync(mappedPath, constants.R_OK | constants.W_OK); } catch (fsErr) {
|
||||
const msg = `File not accessible: ${mappedPath}\n${(fsErr as Error).message}`;
|
||||
db.prepare("UPDATE jobs SET status = 'error', output = ?, exit_code = 1, completed_at = datetime('now') WHERE id = ?").run(msg, job.id);
|
||||
emitJobUpdate(job.id, 'error', msg);
|
||||
db.prepare("UPDATE review_plans SET status = 'error' WHERE item_id = ?").run(job.item_id);
|
||||
@@ -197,7 +204,8 @@ async function runJob(job: Job): Promise<void> {
|
||||
if (node.series_path) cmd = cmd.replaceAll('/series/', node.series_path.replace(/\/$/, '') + '/');
|
||||
for await (const line of execStream(node, cmd)) { outputLines.push(line); flush(); }
|
||||
} else {
|
||||
const proc = Bun.spawn(['sh', '-c', job.command], { stdout: 'pipe', stderr: 'pipe' });
|
||||
const mappedCmd = applyPathMappingsToCommand(job.command);
|
||||
const proc = Bun.spawn(['sh', '-c', mappedCmd], { stdout: 'pipe', stderr: 'pipe' });
|
||||
const readStream = async (readable: ReadableStream<Uint8Array>, prefix = '') => {
|
||||
const reader = readable.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
Reference in New Issue
Block a user