# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
# Start development server
npm start                  # node index.js --node_env=development

# Run full test suite (lint + format + unit tests)
npm test

# Run tests only (no lint/format)
npm run test:run           # nyc mocha test 'test/**/*.js' --exit

# Run a single test file
npx mocha test/unit/storage/s3.test.js --exit

# Lint
npx eslint .
```

## Architecture

The server follows a layered request pipeline:

```
HTTP Request → Router (lib/controller/index.js)
            → HandlerFactory (lib/handlers/factory.js)
            → Handler (Image / Default / Plugin)
            → StorageFactory (lib/storage/factory.js)
            → Cache (lib/cache/index.js)
            → HTTP Response
```

**Entry point:** `index.js` optionally forks via Node cluster. `lib/index.js` (Server class) bootstraps HTTP/HTTPS/HTTP2, attaches middleware, and starts the router.

**Router** (`lib/controller/index.js`) handles special API routes (`/api/flush`, `/api/recipes`, `/api/routes`, `/api/status`) and a catch-all for assets. Middleware chain: favicon filter → body parser → request logger → seek (range requests) → JWT auth.

**HandlerFactory** resolves which handler to use: workspace plugins/recipes/routes take priority, then format-based dispatch (gif/jpg/jpeg/json/png/webp → ImageHandler, everything else → DefaultHandler).

**ImageHandler** (`lib/handlers/image.js`) uses Sharp as the primary processor and Jimp/gifwrap for GIF support. Supports resize, crop, format conversion, quality, gravity, blur, rotation, smart crop, EXIF extraction, and color palette via node-vibrant.

**Storage layer** is factory-selected based on config or URL prefix (`s3/…`, `http/…`, or default disk). Adapters: `disk.js`, `s3.js`, `http.js`, `missing.js`.

**Caching** uses `@caruuto/cache` (external package) with directory or Redis backends. Cache keys are SHA1-normalized. Requests for the same resource are deduplicated by `lib/workQueue.js` — multiple concurrent requests share a single processing job.

**Workspace** (`lib/models/workspace.js`) loads recipes (image transform presets), routes (conditional redirect rules), and plugins from the filesystem and watches for changes via Chokidar. Routes can match on language, user-agent, and geolocation (MaxMind).

**Configuration** (`config.js`) uses `convict` with schema validation. Runtime config lives in `config/config.{NODE_ENV}.json`. Key sections: `server`, `images`, `assets`, `caching`, `logging`, `security`, `auth`, `headers`, `multiDomain`.

**Multi-domain:** Per-domain config overrides are supported. DomainManager (`lib/models/domain-manager.js`) loads domain-specific workspaces and config.

## Testing

Tests live in `test/unit/` and `test/acceptance/`. Framework is Mocha + Sinon + Should. AWS interactions are mocked with `aws-sdk-mock`, Redis with `fakeredis`, HTTP with `nock`, and module-level dependencies with `proxyquire`. Coverage via NYC (lcov).
