Commit Graph
71 Commits
Author SHA1 Message Date
anthony c07663aa7b feat(seo): return a real 404 status for unmatched routes 2026-08-02 10:23:07 +02:00
anthony b2636e20cf feat(seo): redirect / to /fr/ or /en/ server-side based on Accept-Language 2026-08-02 10:21:38 +02:00
anthony 5ff8a865e8 feat(seo): add compression, cache-control headers, configurable frontend dist path 2026-08-02 10:20:22 +02:00
anthonyandClaude Sonnet 5 457913d8d4 feat(video): wire video converters, resolution validation, and timeout into app.js/worker.js
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 22:01:58 +02:00
anthonyandClaude Sonnet 5 9c1f857398 feat(video): add MIME types for mp4/webm/mov/avi/mkv
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 21:59:06 +02:00
anthonyandClaude Sonnet 5 913dbac691 feat(video): add ffmpeg-backed video converter for mp4/webm/mov/avi/mkv
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 21:58:23 +02:00
anthonyandClaude Sonnet 5 886c2e8539 feat(video): add configurable VIDEO_JOB_TIMEOUT_MS
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 21:57:37 +02:00
anthony 433ff3b726 feat(audio): add MIME types for mp3/wav/ogg/flac/aac/m4a 2026-08-01 14:17:25 +02:00
anthony 050ea5ba64 feat(audio): wire audio converters and bitrate validation into app.js/worker.js 2026-08-01 14:15:13 +02:00
anthony 05be353664 feat(audio): add ffmpeg-backed audio converter for mp3/wav/ogg/flac/aac/m4a 2026-08-01 14:13:09 +02:00
anthonyandClaude Sonnet 5 ef6de6b583 feat(archive): wire archive converters, validation, and extension parsing into app.js/worker.js
Also fixes a third double-extension bug the plan missed: app.js derived
each job's uuid via path.basename(file.filename, path.extname(...)),
which only strips the last dot segment. For a compound extension like
tar.gz this left "<uuid>.tar" as the "uuid", overflowing the uuid
column (Char(36)) and crashing the request. Replaced with
stripExtension(). Also bumped rateLimitMaxJobs in jobs.test.js's config
override — the file's cumulative POST /api/jobs calls across all tests
now exceeds the production default (20/window) once the archive tests
are included, causing spurious connection resets independent of any
real bug.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 13:00:01 +02:00
anthonyandClaude Sonnet 5 a8cdb06d5c feat(archive): add MIME types and compound-extension aliases for archive formats
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 12:55:56 +02:00
anthonyandClaude Sonnet 5 ceddeddf3e feat(archive): add rar extraction support
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 12:55:10 +02:00
anthonyandClaude Sonnet 5 a66143d312 feat(archive): add 7z and tar.7z converters
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 12:53:36 +02:00
anthonyandClaude Sonnet 5 a76b10a43f feat(archive): add tar.bz2 converter via 7za
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 12:52:29 +02:00
anthonyandClaude Sonnet 5 c9251e66e2 feat(archive): add tar and tar.gz converters
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 12:51:34 +02:00
anthonyandClaude Sonnet 5 d68694ead8 feat(archive): add zip converter with compression level and zip-slip protection
archiver v8 (installed) uses a class-based API (`ZipArchive`) rather than
the factory-function API most examples online still describe — adjusted
createZip() to match after the first test run surfaced the mismatch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 12:49:46 +02:00
anthonyandClaude Sonnet 5 031df9a999 feat(archive): add double-extension-aware filename parsing helper
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 12:47:27 +02:00
anthonyandClaude Sonnet 5 db3e73860b feat(api): expose outputSizeBytes on job status
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 16:14:38 +02:00
anthony 86b555b334 feat: register ebook converter in the app so the API serves the new family
Also fixes a real bug found via the fb2 API test: file-type sniffs a
real fb2 file's XML declaration as generic "xml", not "fb2" and not
undetected, so it never reached the undetectable-format fallback added
in the previous commit. Added an fb2->xml alias in normalizeFormat,
same pattern as the existing azw3->mobi one.
2026-07-31 13:29:06 +02:00
anthony 977dac35d9 feat: add ebook MIME types, fix azw3/mobi detection collision, trust undetectable ebook formats 2026-07-31 13:25:46 +02:00
anthony 534630ab4e feat: give ebook conversions their own worker timeout and register the converter 2026-07-31 13:24:49 +02:00
anthony f796c0bd97 feat: add configurable ebookJobTimeoutMs to config 2026-07-31 13:23:30 +02:00
anthony b95e371989 feat: add ebook converter wrapping Calibre's ebook-convert CLI 2026-07-31 13:23:01 +02:00
anthonyandClaude Sonnet 5 e7c30202f5 feat: register font/dfont converters in the app and worker
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 12:59:19 +02:00
anthonyandClaude Sonnet 5 be50f1f076 feat: add font MIME types and fix dfont/ico detection collision
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 12:57:35 +02:00
anthonyandClaude Sonnet 5 2cde4ec035 feat: add source-only dfont font converter
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 12:56:13 +02:00
anthonyandClaude Sonnet 5 e5e4f31e9b feat: add bidirectional ttf/otf/woff font converter
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 12:55:19 +02:00
anthonyandClaude Sonnet 5 598781f417 feat: register ICO/HEIC/HEIF converters in the worker and pass iconSize through
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 10:16:25 +02:00
anthonyandClaude Sonnet 5 67bdfbf3de feat: wire ICO/HEIC/HEIF converters and iconSize validation into the API
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 10:15:14 +02:00
anthonyandClaude Sonnet 5 be43eac13a feat: thread iconSize through jobRepository
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 10:13:15 +02:00
anthonyandClaude Sonnet 5 8795f65055 feat: add source-only HEIC/HEIF image converter
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 10:10:41 +02:00
anthonyandClaude Sonnet 5 05ef7dfca1 feat: add bidirectional ICO image converter
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 10:09:56 +02:00
anthonyandClaude Sonnet 5 39b296f5d3 feat: add ico MIME type and heif->heic extension alias
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 10:08:46 +02:00
anthony b40a7d340f Add support for csv + xlsx 2026-07-31 09:17:08 +02:00
anthonyandClaude Sonnet 5 756e875fd9 feat: add md<->txt passthrough document converters
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 08:34:51 +02:00
anthonyandClaude Sonnet 5 70c0c5ce6b feat: add md<->docx document converters
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 08:33:31 +02:00
anthonyandClaude Sonnet 5 82533ca436 feat: add md<->pdf document converters
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 08:31:53 +02:00
anthonyandClaude Sonnet 5 1595c5e0af feat: add md<->html document converters
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 08:31:00 +02:00
anthonyandClaude Sonnet 5 28b6edac82 feat: add MIME plumbing for markdown (.md) format
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 08:29:55 +02:00
anthonyandClaude Sonnet 5 e4507ca8a0 Fix broken migration fallback in CLAUDE.md; add defensive null guards
The documented shadow-database-free fallback for generating migration SQL
(--from-migrations ... --to-schema-datamodel ...) was never actually tested
and fails for the same P3014 reason `migrate dev` does, since
--from-migrations also requires --shadow-database-url internally. Verified
against the local dev DB that --from-schema-datasource (live introspection,
no shadow DB) diffed against --to-schema-datamodel (static file read) works
in both the no-op case and a real ADD COLUMN case, and documented that
instead. Also corrected the inaccurate claim that this matched Task 3's
approach (Task 3 used --from-empty) and moved the suggested SQL output path
out of the repo root into the OS temp directory.

Also brings markFailed's errorMessage/errorLog params in line with markDone's
existing ?? null guard, and adds orderBy to findExpiredJobs to match
findPendingJobs, for consistency.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 02:05:37 +02:00
anthonyandClaude Sonnet 5 c42fe68b36 fix: isolate per-job cleanup errors and guard markDone against undefined
runCleanup previously had no try/catch around each expired job, so one
job's markCleaned/delete failure would abort the whole pass, leaving
later expired jobs' files undeleted for that run. Each iteration is now
wrapped in a try/catch that logs and continues; the returned count only
reflects jobs that actually completed the delete+markCleaned sequence.

markDone now guards outputPath/outputMimeType/outputSizeBytes/
conversionDurationSeconds with `?? null`, matching the guard createJob
already has on `quality` — Prisma treats `undefined` in a data object as
"leave the column alone" rather than binding NULL like the old raw SQL
did. Currently unreachable in practice since the worker always passes
real values, but keeps the repository defensive and consistent.

Added a cleanup.test.js case that monkey-patches
prisma.conversionJob.update to reject for one job's cleanedAt update,
asserting a later expired job in the same batch still gets cleaned.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 01:54:14 +02:00
anthonyandClaude Sonnet 5 4c9fe8f616 Wire the app, worker, and cleanup entry points onto Prisma Client
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>
2026-07-31 01:32:54 +02:00
anthony 3a04da3180 Rewrite the data access layer onto Prisma Client 2026-07-31 01:27:18 +02:00
anthonyandClaude Sonnet 5 5e0b832fce Add buildDatabaseUrl and a CLI helper to print it
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 01:11:35 +02:00
anthonyandClaude Sonnet 5 4cb9d76176 feat: validate and persist per-file quality in POST /api/jobs
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 23:30:23 +02:00
anthonyandClaude Sonnet 5 d827f55e46 feat: pass job quality through to converters in the worker
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 23:30:16 +02:00
anthonyandClaude Sonnet 5 fd99453e38 feat: opt-in JPEG-embed quality for image-to-PDF conversion
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 23:30:08 +02:00
anthonyandClaude Sonnet 5 57d7dac2b5 feat: support quality/compressionLevel options in image converters
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 23:03:39 +02:00
anthonyandClaude Sonnet 5 8caab530e7 feat: add quality column to conversion_jobs
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 23:02:48 +02:00