# node-briks/image-processing architecture

> Architecture diagram of the GitHub repository node-briks/image-processing, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/node-briks/image-processing
- Repository: https://github.com/node-briks/image-processing

## Overview

#### 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: [`src/utills/images.ts`](https://github.com/node-briks/image-processing/blob/master/src/utills/images.ts) (Multer disk upload), [`src/service/index.ts`](https://github.com/node-briks/image-processing/blob/master/src/service/index.ts) (imageService), [`src/storage`](https://github.com/node-briks/image-processing/tree/master/src/storage) (src/storage), [`src/routes/index.ts`](https://github.com/node-briks/image-processing/blob/master/src/routes/index.ts) (POST / router)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Runtime"]
  node_node_runtime{{"Node.js / ts-node-dev<br/>runtime<br/>[package.json]"}}
  node_node_entry["Application entry<br/>Express bootstrap<br/>[index.ts]"]
end

subgraph group_http["HTTP Upload"]
  node_node_export["Route export boundary<br/>module boundary<br/>[index.ts]"]
  node_node_router["POST / router<br/>Express router<br/>[index.ts]"]
  node_node_client(("Multipart client<br/>HTTP caller"))
  node_node_multer["Multer disk upload<br/>multipart middleware<br/>[images.ts]"]
  node_node_response["JSON success response<br/>HTTP response<br/>[index.ts]"]
end

subgraph group_processing["Variant Processing"]
  node_node_service["imageService<br/>request orchestrator<br/>[index.ts]"]
  node_node_subject["Processing subject<br/>observer dispatcher<br/>[index.ts]"]
  node_node_observers["Image observers<br/>resize work units<br/>[index.ts]"]
  node_node_sharp{{"Sharp / libvips<br/>native image transform"}}
end

subgraph group_storage["Local Storage"]
  node_node_storage[("src/storage<br/>local filesystem directory")]
  node_node_source["Stored original<br/>input image file"]
  node_node_variants["WebP derivatives<br/>output image files"]
end

node_node_failure(("Unhandled failures<br/>failure boundary"))

node_node_runtime -->|"runs"| node_node_entry
node_node_client -->|"POST / multipart image"| node_node_router
node_node_entry -->|"mounts"| node_node_export
node_node_export -->|"exports"| node_node_router
node_node_router -->|"applies first"| node_node_multer
node_node_multer -->|"writes upload"| node_node_storage
node_node_storage -->|"contains"| node_node_source
node_node_multer -->|"passes req.file.path"| node_node_service
node_node_service -->|"creates and triggers"| node_node_subject
node_node_subject -->|"dispatches sequentially"| node_node_observers
node_node_observers -->|"invokes per width"| node_node_sharp
node_node_source -->|"source path"| node_node_sharp
node_node_sharp -->|"writes WebP outputs"| node_node_variants
node_node_storage -->|"contains"| node_node_variants
node_node_sharp -->|"returns OutputInfo records"| node_node_service
node_node_service -->|"returns data"| node_node_response
node_node_response -->|"200 JSON"| node_node_client
node_node_multer -.->|"malformed uploads and collisions"| node_node_failure
node_node_sharp -.->|"transform failures"| node_node_failure

click node_node_runtime "https://github.com/node-briks/image-processing/blob/master/package.json"
click node_node_entry "https://github.com/node-briks/image-processing/blob/master/index.ts"
click node_node_export "https://github.com/node-briks/image-processing/blob/master/src/index.ts"
click node_node_router "https://github.com/node-briks/image-processing/blob/master/src/routes/index.ts"
click node_node_multer "https://github.com/node-briks/image-processing/blob/master/src/utills/images.ts"
click node_node_service "https://github.com/node-briks/image-processing/blob/master/src/service/index.ts"
click node_node_subject "https://github.com/node-briks/image-processing/blob/master/src/service/index.ts"
click node_node_observers "https://github.com/node-briks/image-processing/blob/master/src/service/index.ts"
click node_node_storage "https://github.com/node-briks/image-processing/tree/master/src/storage"
click node_node_source "https://github.com/node-briks/image-processing/tree/master/src/storage"
click node_node_variants "https://github.com/node-briks/image-processing/tree/master/src/storage"
click node_node_response "https://github.com/node-briks/image-processing/blob/master/src/routes/index.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_node_runtime,node_node_entry toneBlue
class node_node_export,node_node_router,node_node_client,node_node_multer,node_node_response toneAmber
class node_node_service,node_node_subject,node_node_observers,node_node_sharp toneMint
class node_node_storage,node_node_source,node_node_variants toneRose
class node_node_failure toneNeutral
```

## Components

### Runtime

- [Node.js / ts-node-dev](https://github.com/node-briks/image-processing/blob/master/package.json): runtime · Executes the TypeScript API process. · `package.json`
- [Application entry](https://github.com/node-briks/image-processing/blob/master/index.ts): Express bootstrap · Creates the app, mounts routing, and listens on port 3000. · `index.ts`

### HTTP Upload

- [Route export boundary](https://github.com/node-briks/image-processing/blob/master/src/index.ts): module boundary · `src/index.ts`
- [POST / router](https://github.com/node-briks/image-processing/blob/master/src/routes/index.ts): Express router · Composes upload middleware and the image handler. · `src/routes/index.ts`
- **Multipart client**: HTTP caller · Sends one image in the required image field.
- [Multer disk upload](https://github.com/node-briks/image-processing/blob/master/src/utills/images.ts): multipart middleware · Parses multipart input and places a disk-file descriptor in req.file. · `src/utills/images.ts`
- [JSON success response](https://github.com/node-briks/image-processing/blob/master/src/routes/index.ts): HTTP response · Returns success true and Sharp output metadata. · `src/routes/index.ts`

### Variant Processing

- [imageService](https://github.com/node-briks/image-processing/blob/master/src/service/index.ts): request orchestrator · Builds and executes a fresh variant pipeline per upload. · `src/service/index.ts`
- [Processing subject](https://github.com/node-briks/image-processing/blob/master/src/service/index.ts): observer dispatcher · Sequentially awaits registered work units. · `src/service/index.ts`
- [Image observers](https://github.com/node-briks/image-processing/blob/master/src/service/index.ts): resize work units · One observer is registered for each target width. · `src/service/index.ts`
- **Sharp / libvips**: native image transform · Resizes, WebP-encodes at quality 80, and returns output metadata.

### Local Storage

- [src/storage](https://github.com/node-briks/image-processing/tree/master/src/storage): local filesystem directory · Shared durable location for uploaded originals and generated variants. · `src/storage`
- [Stored original](https://github.com/node-briks/image-processing/tree/master/src/storage): input image file · Uses the client-provided filename and req.file.path. · `src/storage`
- [WebP derivatives](https://github.com/node-briks/image-processing/tree/master/src/storage): output image files · Writes 50, 100, 200, 500, and 600px variants with source extensions retained. · `src/storage`

### Other components

- **Unhandled failures**: failure boundary · Missing upload validation, collisions, and transform errors lack centralized handling.

## Connections

- 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
