The X-File-Results header contained raw JSON with non-ASCII characters
from filenames (Chinese, Japanese, etc.), violating RFC 7230. Node.js
threw ERR_INVALID_CHAR on writeHead(). Fixed by wrapping the JSON in
encodeURIComponent() on the backend and decodeURIComponent() on the
frontend, ensuring only ASCII goes into the header while preserving
the original filenames after decoding.
Closes#133
- Refactor use-tool-processor and use-pipeline-processor hooks
- Enhance dropzone component with improved UX
- Improve seam carving with better error handling and tests
- Add JXL format encoding support to format-encoders
- Update tool routes for consistent format handling
- Add dropzone unit tests
- Replace [object Object] errors with readable messages across all 20+ API
routes by normalizing Zod validation errors to strings (formatZodErrors)
- Add parseApiError() on frontend to defensively handle any details type
- Add global Fastify error handler with full stack traces in logs
- Fix image-to-pdf auth: Object.entries(headers) → headers.forEach()
- Fix passport-photo: safeParse + formatZodErrors, safe error extraction
- Fix OCR silent fallbacks: log exception type/message when falling back,
include actual engine used in API response and Docker logs
- Fix split tool: process all uploaded images, combine into ZIP with
subfolders per image
- Fix batch support for blur-faces, strip-metadata, edit-metadata,
vectorize: add processAllFiles branch for multi-file uploads
- Docker: LOG_LEVEL=debug, PYTHONWARNINGS=default for visibility
- Add Playwright e2e tests verifying all fixes against Docker container
Reject non-SVG files with a clear error message instead of letting Sharp
fail with cryptic HEIF/corrupt header errors. Applies to both single-file
and batch endpoints.
- Add clientJobId field support for SSE progress correlation
- Add updateJobProgress calls matching generic batch route pattern
- Use sanitizeFilename() instead of basename() for security
- Map Zod errors to {path, message} format for consistency
- Include errors array in all-failed response body
The generic batch route validates image buffers by magic bytes, which
fails for SVG input. This adds a dedicated /batch endpoint that sanitizes
each SVG individually before conversion, using p-queue for concurrency
and streaming the results as a ZIP with X-File-Results header.
Also extracts shared conversion logic into a reusable convertSvg helper
to avoid duplication between single-file and batch endpoints.
Sharp cannot encode HEVC directly. Use encodeHeic() (same as convert tool)
to go through heif-enc. Also decode HEIF before Sharp for preview generation.
Hoist NON_PREVIEWABLE set to module scope.
Add user-configurable DPI (36-1200) and quality (1-100) instead of
hardcoded values. Support avif, tiff, gif, heif output in addition to
png, jpg, webp. Width is now optional, defaulting to SVG intrinsic size
at the given DPI. Generate browser-previewable webp thumbnails for
non-browser formats (tiff, heif). Remove unused _contentType variable.
SVG files were rejected by the convert endpoint because
validateImageBuffer only recognized raster magic bytes. This adds
text-based SVG detection, sanitization in the tool factory, and
proper Sharp density handling so SVG-to-raster conversion works
through the standard convert route.
Add 6 tools for format conversion and optimization extras:
- svg-to-raster: SVG to PNG/JPG/WebP at custom resolution
- vectorize: raster to SVG via potrace (B&W and color modes)
- gif-tools: animated GIF resize, frame extraction, optimization
- bulk-rename: pattern-based file renaming with ZIP output
- favicon: generate all favicon/app icon sizes with manifest.json
- image-to-pdf: combine images into PDF using pdfkit