How node-briks/image-processing works
Purpose and Entry Point
This is a TypeScript/Express image-processing API. A multipart POST / accepts one image, persists it locally, then generates five WebP derivatives (50, 100, 200, 500, 600px wide).
The process starts in index.ts, which creates the Express application, mounts the exported router, and listens on port 3000. src/index.ts is the internal export boundary for routing.
Paths: index.ts, src/index.ts, src/routes/index.ts.
HTTP and Upload Boundary
The router exposes POST / and composes Multer middleware before the image handler. The required multipart field is image; Multer writes the original upload before service logic executes and supplies its disk-file descriptor through req.file.
Upload handling is a hard boundary between HTTP/multipart parsing and processing. There is no JSON request flow.
Paths: src/routes/index.ts, src/utills/images.ts.
Local Storage Infrastructure
Multer uses disk storage targeting src/storage, with the client-provided original filename. This directory is both the durable input location and output location for generated variants. The service consumes req.file.path rather than in-memory bytes.
This introduces filesystem dependencies: the storage directory must exist, and original-name collisions can overwrite files.
Paths: src/utills/images.ts, src/storage.
Processing Orchestration
imageService is the request-level orchestrator. It creates a subject for the uploaded file, registers one image observer for each target width, triggers processing, and returns collected sharp.OutputInfo records as JSON.
The orchestration is currently request-scoped: each upload builds a fresh subject and observer set. Processing is sequential because the subject awaits each observer in order; a failure prevents a normal success response for subsequent work.
Paths: src/service/index.ts, src/routes/index.ts.
Observer-Based Variant Pipeline
The service defines an Observer-style abstraction: a subject owns registered work units, while each ImageObserver encapsulates one resize target. The subject does not need image-specific knowledge beyond the observer contract, making additional variants or work types attachable without changing dispatch logic.
Each observer invokes Sharp against the stored source path, preserves aspect ratio while setting width, encodes WebP at quality 80, and writes an output named with its target width prefix. Output filenames retain the source extension despite containing WebP data.
Paths: src/service/index.ts, src/storage.
Runtime and External Dependencies
The runtime is Node.js with TypeScript executed through ts-node-dev; package behavior is defined in package.json. Express provides HTTP routing, Multer handles multipart parsing/disk writes, and Sharp delegates native image transforms to libvips. There is no database, queue, cloud storage, authentication provider, or external API integration.
Paths: package.json, tsconfig.json, index.ts.
Response and Failure Boundary
On success, the service returns HTTP 200 with { success: true, data }, where data is Sharp’s actual output metadata for all derivatives. The current architecture has no explicit validation for missing files, upload-size/type restrictions, collision avoidance, or centralized Express error middleware; malformed uploads and Sharp failures are therefore important unhandled failure boundaries.
Paths: src/service/index.ts, src/routes/index.ts, src/utills/images.ts.
Main entry points: images.ts Multer disk upload · service/index.ts imageService · storage src/storage · routes/index.ts POST / router
Components 15
Runtime
- Node.js / ts-node-dev · Executes the TypeScript API process.
package.json - Application entry · Creates the app, mounts routing, and listens on port 3000.
index.ts
HTTP Upload
- Route export boundary
src/index.ts - POST / router · Composes upload middleware and the image handler.
src/routes/index.ts - Multipart client · Sends one image in the required image field.
- Multer disk upload · Parses multipart input and places a disk-file descriptor in req.file.
src/utills/images.ts - JSON success response · Returns success true and Sharp output metadata.
src/routes/index.ts
Variant Processing
- imageService · Builds and executes a fresh variant pipeline per upload.
src/service/index.ts - Processing subject · Sequentially awaits registered work units.
src/service/index.ts - Image observers · One observer is registered for each target width.
src/service/index.ts - Sharp / libvips · Resizes, WebP-encodes at quality 80, and returns output metadata.
Local Storage
- src/storage · Shared durable location for uploaded originals and generated variants.
src/storage - Stored original · Uses the client-provided filename and req.file.path.
src/storage - WebP derivatives · Writes 50, 100, 200, 500, and 600px variants with source extensions retained.
src/storage
Other components
- Unhandled failures · Missing upload validation, collisions, and transform errors lack centralized handling.
Connections 19
- Node.js / ts-node-dev → Application entry: runs
- Multipart client → POST / router: POST / multipart image
- Application entry → Route export boundary: mounts
- Route export boundary → POST / router: exports
- POST / router → Multer disk upload: applies first
- Multer disk upload → src/storage: writes upload
- src/storage → Stored original: contains
- Multer disk upload → imageService: passes req.file.path
- imageService → Processing subject: creates and triggers
- Processing subject → Image observers: dispatches sequentially
- Image observers → Sharp / libvips: invokes per width
- Stored original → Sharp / libvips: source path
- Sharp / libvips → WebP derivatives: writes WebP outputs
- src/storage → WebP derivatives: contains
- Sharp / libvips → imageService: returns OutputInfo records
- imageService → JSON success response: returns data
- JSON success response → Multipart client: 200 JSON
- Multer disk upload → Unhandled failures: malformed uploads and collisions
- Sharp / libvips → Unhandled failures: transform failures