Plans the replacement of the raw mariadb pool and hand-written
repository with Prisma Client, plus a no-data-loss Prisma Migrate
baseline against the existing conversion_jobs table.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Covers data model, backend threading through registry/image/imageToPdf/worker, frontend controls, validation, and testing for a new quality/compressionLevel option on image conversions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Rename the old CHAR(36) id to uuid (still used for public URLs and file
naming) and add a real auto-increment id as the primary key. Track
input/output file size and conversion duration per job. Cleanup no
longer deletes rows; it marks cleaned_at and skips already-cleaned
expired jobs on later runs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Also fixes a Windows-specific bug in worker.js and cleanup.js: the
"run only if executed directly" guard compared import.meta.url against
`file://${process.argv[1]}`, which never matches on Windows (backslash
path separators, missing extra slash before the drive letter). main()
silently never ran, so the worker process started and exited
immediately without ever polling. Caught during this task's manual
verification of the full upload-convert-download flow. Fixed with
node:url's pathToFileURL, which builds a correct file:// URL cross-platform.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Also adds vitest.config.js with fileParallelism: false. Every DB-backed
test file wipes and reseeds the shared conversion_jobs table in
beforeEach; running test files in parallel (Vitest's default) let one
file's DELETE race another file's just-inserted row against the same
live MariaDB instance, causing intermittent cross-file failures.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Regenerates the sample.png test fixture via sharp itself: the
hand-encoded base64 PNG from the plan had valid magic bytes (enough to
fool file-type's signature check) but was malformed past the header,
which libpng rejected as soon as sharp actually tried to decode it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Also configures the MariaDB pool with timezone: 'auto', since the
default 'local' mode sends dates without timezone conversion and
silently broke expires_at comparisons whenever the app host and DB
server clocks differ (caught by the findExpiredJobs test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
18 bite-sized TDD tasks from project scaffolding through the React
frontend and an end-to-end pipeline test, following the approved design
spec.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>