build: approve better-sqlite3 install script (npm install-scripts policy)
Build & Push Docker Image / test (push) Failing after 17s
Build & Push Docker Image / build-and-push (push) Has been skipped

npm >=11 on node 24 skips non-approved dependency install scripts, so fresh
clones/worktrees never build the better-sqlite3 native bindings and every
build fails with "Could not locate the bindings file". Approving it in
package.json makes the approval travel with the repo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Giancarmine Salucci
2026-07-21 16:42:44 +02:00
co-authored by Claude Fable 5
parent 4ca532b873
commit 4ea12b1299
2 changed files with 43 additions and 82 deletions
+3
View File
@@ -38,5 +38,8 @@
"node-fetch": "^3.3.2",
"web-push": "^3.6.7",
"youtube-transcript": "^1.3.1"
},
"allowScripts": {
"better-sqlite3@12.9.0": true
}
}
+40 -82
View File
@@ -4,7 +4,6 @@
import { getDisplayJobProgress, getJobStatusColor, getJobStatusLabel, isTerminalJobStatus } from '$lib/job-progress.js';
import SourceIcon from '$lib/components/SourceIcon.svelte';
import Waveform from '$lib/components/Waveform.svelte';
import JobErrorLine from '$lib/components/JobErrorLine.svelte';
import { accent } from '$lib/accent.js';
const ACCENT = $derived($accent.value);
@@ -34,27 +33,23 @@
loading = false;
});
async function deleteJobById(jobId: string) {
const job = jobs.find((j) => j.id === jobId);
if (!job) return;
if (!confirm(`Delete "${job.title || job.id}"?`)) return;
const res = await fetch(`/api/jobs/${jobId}`, { method: 'DELETE' });
if (res.ok) jobs = jobs.filter((j) => j.id !== jobId);
}
async function deleteJob(e: MouseEvent, job: Job) {
e.preventDefault();
e.stopPropagation();
await deleteJobById(job.id);
if (!confirm(`Delete "${job.title || job.id}"?`)) return;
const res = await fetch(`/api/jobs/${job.id}`, { method: 'DELETE' });
if (res.ok) jobs = jobs.filter((j) => j.id !== job.id);
}
async function retryJobById(jobId: string) {
const res = await fetch(`/api/jobs/${jobId}/retry`, { method: 'POST' });
async function retryJob(e: MouseEvent, job: Job) {
e.preventDefault();
e.stopPropagation();
const res = await fetch(`/api/jobs/${job.id}/retry`, { method: 'POST' });
if (res.ok) {
const updated = await fetch(`/api/jobs/${jobId}`);
const updated = await fetch(`/api/jobs/${job.id}`);
if (updated.ok) {
const j = await updated.json();
jobs = jobs.map((x) => (x.id === jobId ? j : x));
jobs = jobs.map((x) => (x.id === job.id ? j : x));
}
} else {
const body = await res.json().catch(() => ({}));
@@ -104,16 +99,12 @@
<span>·</span>
<span>{job.audioMode}</span>
{/if}
</div>
{#if ['failed', 'cancelled'].includes(job.status)}
<JobErrorLine
{job}
accentColor={ACCENT}
onRetry={retryJobById}
onDelete={deleteJobById}
/>
{#if ['failed', 'cancelled'].includes(job.status) && job.error}
<span>·</span>
<span class="job-err-inline" title={job.error}>{job.error}</span>
{/if}
</div>
</div>
{#if !isTerminalJobStatus(job.status)}
<div class="job-wave">
@@ -129,11 +120,27 @@
<div class="job-pct mono" style="color: {ACCENT}">
{getDisplayJobProgress(job, { hasTranscript: Boolean(job.segmentsJson) })}%
</div>
{:else}
<div class="job-pct mono" style="color: {getJobStatusColor(job.status)}">
{getJobStatusLabel(job.status)}
</div>
{/if}
<!-- Row actions (hover-revealed, delete for done jobs) -->
<!-- Retry slot (always visible) -->
{#if ['failed', 'cancelled'].includes(job.status)}
<div class="row-retry-slot">
<button
class="row-btn accent"
onclick={(e) => retryJob(e, job)}
aria-label="Retry"
title="Retry"
>↺</button>
</div>
{/if}
<!-- Row actions (hover-revealed, delete only) -->
<div class="row-actions">
{#if job.status === 'done'}
{#if isTerminalJobStatus(job.status)}
<button
class="row-btn danger"
onclick={(e) => deleteJob(e, job)}
@@ -191,64 +198,7 @@
flex-direction: column;
gap: 8px;
}
.job-row {
display: flex;
align-items: center;
gap: 14px;
padding: 16px 20px;
text-decoration: none;
color: var(--text);
transition: background 0.15s;
}
.job-row:hover {
background: rgba(255, 255, 255, 0.04);
}
.job-info {
flex: 1;
min-width: 0;
}
.job-name {
font-size: 14px;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 3px;
}
.job-meta {
font-size: 11.5px;
color: var(--text-muted);
display: flex;
gap: 6px;
}
.job-wave {
flex-shrink: 0;
}
.job-pct {
font-size: 12.5px;
font-weight: 600;
flex-shrink: 0;
}
.row-actions {
display: flex;
gap: 4px;
flex-shrink: 0;
opacity: 0;
transition: opacity 0.15s;
}
.job-row:hover .row-actions {
opacity: 1;
}
…[rtk: elided 73 of 313 lines]…
.job-row[data-status="failed"] .job-name {
color: var(--error-text);
}
@@ -274,6 +224,14 @@
.row-btn.danger:hover {
background: rgba(255, 90, 90, 0.2);
}
.row-btn.accent {
border-color: color-mix(in oklab, var(--accent) 40%, transparent);
background: color-mix(in oklab, var(--accent) 10%, transparent);
color: var(--accent);
}
.row-btn.accent:hover {
background: color-mix(in oklab, var(--accent) 20%, transparent);
}
@media (max-width: 768px) {
.page {