src/db.js imports @prisma/client at runtime, but it was listed under
devDependencies (likely merged with the `prisma` devDependency during
Task 1). A production install that omits dev dependencies would crash
on startup with a missing-module error. `prisma` (the CLI) stays a
devDependency.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Task 4 rewrote src/db.js and src/jobs/jobRepository.js to use Prisma
instead of the hand-rolled mariadb pool. This updates every remaining
call site (app.js, server.js, worker.js, cleanup.js) and the 5 test
files that still referenced getPool/closePool/pool.query, so the app
and full test suite compile and run against Prisma Client.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Marks 0_init as applied via prisma migrate resolve so Prisma's
migration history is in sync with the pre-existing conversion_jobs
table, without running any SQL against the table itself.
Task 3 found Prisma's generated migration SQL never emits an
explicit ENGINE=... clause, same root cause as the already-accepted
collation exception (no schema-level attribute exists). No practical
impact: the baseline never executes this SQL against the real DB,
and any fresh deploy still gets InnoDB from the server default.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Review of Task 1 (d86245a) found two issues:
1. prisma/schema.prisma didn't reproduce db/schema.sql's DDL exactly.
Add @db.DateTime(0) to createdAt/updatedAt/expiresAt/cleanedAt (Prisma
otherwise defaults to DATETIME(3)), and explicit map: names on the
uuid unique constraint and status/expiresAt indexes so they match the
real table's uniq_uuid/idx_status/idx_expires_at. Verified via
`prisma migrate diff --from-empty --to-schema-datamodel`, which now
shows DATETIME(0)/CURRENT_TIMESTAMP(0) and the correct names. Table
collation and updated_at's ON UPDATE CURRENT_TIMESTAMP remain
documented, accepted gaps with no schema-level fix in Prisma's mysql
provider.
2. The original @prisma/client@6/prisma@6 pin used --force without
diagnosing why. Reinstalled with `npm install @prisma/client@6
prisma@6 --save-dev` (no --force) directly against this project's
node_modules: it completed cleanly with no conflicts, confirming
--force was unnecessary.
`prisma validate`, `prisma generate`, and the full test suite
(69 passed, 4 pre-existing failures unrelated to this change) all pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Task 1's reviewer found the original schema.prisma didn't reproduce
db/schema.sql's DDL (DATETIME(3) vs DATETIME, auto-generated index
names, no explicit precision on defaults). Verified the real DDL via
SHOW CREATE TABLE and empirically confirmed @db.DateTime(0) plus
explicit map: names close the gap. Two remaining differences (table
collation, no DB-level ON UPDATE for updatedAt) are Prisma/MySQL
provider limitations with no schema-level fix; documented as
accepted, per user decision, since the baseline never executes this
SQL against the real database and all writes go through Prisma.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Task-by-task plan to replace the mariadb pool/repository with
Prisma Client and baseline Prisma Migrate against the existing
conversion_jobs table without data loss.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>