Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
# Design — @suaveplan/caddy-imgproxy
## File layout
```text
packages/media/image/caddy-imgproxy/
package.json # 0.1.0, exports per feature module
vite.config.ts # multi-entry build mirroring exports
vitest.config.ts # provider: istanbul, thresholds 100/100/100/100
tsconfig.lib.json
README.md
tests/setup/polyfills.ts
src/
index.ts # explicit named re-exports
parse/
parse-url.ts # parseImgproxyUrl
parse-url.test.ts
parse-url.md
index.ts # explicit named barrel
dimensions/
calculate-dimensions.ts # calculateDimensions
calculate-dimensions.test.ts
calculate-dimensions.md
index.ts
gravity/
gravity.ts # gravityToImgproxy + GRAVITY_MAP
gravity.test.ts
gravity.md
index.ts
operation/
operation.ts # operationToImgproxy
operation.test.ts
operation.md
index.ts
signing/
sign-path.ts # signImgproxyPath, HashLike injection
sign-path.test.ts
sign-path.md
index.ts
url-builder/
url-builder.ts # buildImgproxyUrl orchestrator
url-builder.test.ts
url-builder.md
index.ts
domain/
extract-domain.ts
extract-domain.test.ts
extract-domain.md
index.ts
handler/
handler.ts # ImgproxyHandler orchestrator
handler.test.ts
handler.md
index.ts
config/
config.ts # ImgproxyConfigSchema, parseConfig
config.test.ts
config.md
index.ts
error-codes/
error-codes.ts # CADDY_IMGPROXY_CODES + CaddyImgproxyError
error-codes.test.ts
error-codes.md
index.ts
telemetry/
telemetry.ts # counters + histogram
telemetry.test.ts
telemetry.md
index.ts
types/
types.ts # ParsedImgproxyUrl, ImgproxyConfig, RewriteResult
index.ts
```
## URL grammar (verbatim port of Go regex)
```text
^/
([su]) # 1 signed | unsigned
([vcfsr])? # 2 op (v/c/f/s/r) opt
(tl|tr|bl|br|[tblrc])? # 3 gravity opt
(?:
([1-9]\d*):([1-9]\d*) # 4,5 aspect W:H
| ([1-9]\d*)x(\d+) # 6,7 pixel WxH (W>0)
| (0)x([1-9]\d*) # 8,9 pixel 0xH (auto-width)
| ([1-9]\d*) # 10 square shorthand
)?
((?:[wh][1-9]\d*|q(?:100|[1-9]\d?))*) # 11 modifiers
/(.+)\.([a-z]+)$ # 12 path / 13 format
```
Modifier sub-regex: `([whq])(\d+)` — extract `w<int>`, `h<int>`, `q<int>` in any order.
## Dimensions algorithm
```ts
if (!hasDims) return { width: 0, height: 0 };
if (!isAspect) return { width: pixelW, height: pixelH };
// aspect path
if (hintType === "h" && hintValue > 0) {
height = hintValue;
width = Math.trunc((height * aspectW) / aspectH);
} else {
width = hintValue > 0 ? hintValue : defaultWidth;
height = Math.trunc((width * aspectH) / aspectW);
}
```
(`Math.trunc` matches Go integer division.)
## Operation → imgproxy table
| op | both W&H | only W | only H | none |
|---|---|---|---|---|
| cover | `g:<g>/rs:fill:W:H` | `g:<g>/w:W` | `g:<g>/h:H` | `""` |
| fit | `rs:fit:W:H` | `w:W` | `h:H` | `""` |
| crop | `g:<g>/c:W:H` | `""` | `""` | `""` |
| stretch | `rs:force:W:H` | `""` | `""` | `""` |
| resize | — | `w:W` | `h:H` | `""` |
| `""` (passthrough) | `""` | `""` | `""` | `""` |
## Signing
`HMAC-SHA256(keyBytes, saltBytes || pathBytes)` → base64url, no padding. Implementation uses `hmac` from `@suaveplan/crypto-hash` with `Uint8Array` inputs. Hex key/salt decoded via `fromHex`.
## Telemetry
| Instrument | Kind | Tags | Where |
|---|---|---|---|
| `caddy_imgproxy_parse_total` | counter | `outcome` ∈ `ok|invalid|unknown_op|missing_dims` | `parseImgproxyUrl` |
| `caddy_imgproxy_rewrite_total` | counter | `outcome` ∈ `rewritten|passthrough|invalid`, `operation` | `ImgproxyHandler.rewrite` |
| `caddy_imgproxy_sign_total` | counter | `mode` ∈ `signed|unsafe` | `buildImgproxyUrl` |
| `caddy_imgproxy_rewrite_duration_ms` | histogram | — | `ImgproxyHandler.rewrite` |
## Tier & deps
Universal-tier. Deps: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/crypto-hash`, `@suaveplan/opentelemetry`, `@opentelemetry/api`, `tslib`, `zod`. DevDeps: `@suaveplan/testing`, `@vitest/coverage-istanbul`, `typescript`, `vite`, `vite-plugin-dts`, `vitest`, `@types/node`.
## Test plan
Re-port every `imgproxy_test.go` case to `parse-url.test.ts` + `dimensions/...test.ts` + `operation/...test.ts` + `gravity/...test.ts` + `domain/...test.ts` + `url-builder/...test.ts`. Plus genesis-only tests: Zod boundary failures, error-code reachability, telemetry emission via a real `MeterProvider`, signing KAT against a fixed key/salt pair (mirrors Go `signPath` output).