4.7 KiB
Migrate @suaveplan/image to genesis
Package: @suaveplan/image
Status: PROPOSED
Type: spec-conformance
Why
@suaveplan/image exists upstream (../suaveplan/packages/universal/image) but has not been migrated to genesis. It provides image format detection, metadata extraction, resize math, crop validation, and transform pipeline planning — primitives consumed by compress-image and downstream UI packages. Migrating it unblocks full enterprise-quality parity and brings the package into compliance with genesis conventions: defineCodes, Zod boundaries, OTel instrumentation, explicit barrels, and 100% coverage.
What changes
- ADDED:
IMAGE_CODES— stabledefineCodes("IMAGE", [...])registry replacing upstreamErrorCodes.registerManyside effect. - ADDED:
ImageError— extendsSuaveplanError<ImageCode>with typedImageErrorContext. - ADDED: Zod schemas for every public boundary (
ImageProcessorConfigSchema,CropRegionSchema,ResizeOptionsSchema,TransformOpSchema,TransformPipelineSchema,ImageMetadataSchema). - ADDED: OTel counters (
image.metadata.extracted_total,image.transform.planned_total) and histograms (image.metadata.extract_duration_ms,image.transform.plan_duration_ms) emitted from production paths. - ADDED:
ImageProcessorspans forextractMetadataandplanTransform. - ADDED:
AbortSignalsupport onextractMetadataandplanTransform(pre-abort short-circuit). - MODIFIED:
ImageProcessorconstructor now validates config via Zod and accepts optionaltracer/meterfrom@opentelemetry/api. - MODIFIED:
PipelineBuilderquality setter now clamps to[1, 100]and throwsIMAGE_CODES.DIMENSIONS_INVALIDon bad input. - REMOVED: Side-effect import
import "./error-codes.js"— package is nowsideEffects: false. - REMOVED:
@deprecatedJSDoc aliases (unknownFormat,invalidDimensions,invalidCrop,metadataParseFailed,invalidTransform) — replaced by prose-only backward-compat re-exports.
Out of scope
- Actual pixel buffer encoding/decoding —
compress-imageandexifalready cover compression and metadata I/O. This package remains a metadata + transform-planning library. - Browser-specific APIs (
HTMLImageElement,CanvasRenderingContext2D) — the package is universal-tier. - Network fetch helpers — callers supply
Uint8Arraydirectly.
Source mapping
This change derives from ../suaveplan/enterprise/image.md.
| Requirement | Source lines | Notes |
|---|---|---|
| Zero browser / Node / React dependencies | L37 | verbatim |
| Zod schemas for public types | L38-L39 | extended: wired at every boundary |
| OpenTelemetry instrumentation | L41-L42 | extended: counters + histograms + spans |
Structured errors via @suaveplan/error |
L42 | extended: defineCodes + SuaveplanError |
AbortSignal propagation |
L43 | extended: pre-abort on sync entrypoints |
| Test coverage ≥ 95% | L50 | extended: genesis requires 100% |
| No mocks | L53 | verbatim |
sideEffects: false |
L55 | verbatim |
| Biome clean | L58 | verbatim |
| Error hierarchy | L61 | verbatim |
Requirements with no source line
| Requirement | Justification |
|---|---|
Explicit named barrel exports (no export *) |
Genesis-wide policy per openspec/AGENTS.md §6a |
Test imports from @suaveplan/testing/runner |
Genesis-wide policy per openspec/AGENTS.md §7 |
Sibling .md for every .ts |
Genesis-wide docs policy per openspec/AGENTS.md §4 |
| Subpath exports per feature module | Genesis-wide tree-shaking policy per openspec/AGENTS.md §6 |
Verification approach
src/error-codes/error-codes.test.ts— covers code registry, type assertions.src/errors/errors.test.ts— coversImageErrorconstruction, context, cause, legacy alias round-trips.src/types/image-types.test.ts— covers format detection, aspect ratio, resize math, crop validation, MIME mapping.src/processor/processor.test.ts— covers metadata extraction, dimension parsing, size limits, transform planning, pipeline builder chaining, event emission.src/processor/processor.spec-conformance.test.ts— pins OTel instrument emission, Zod boundary rejection, strict-mode behaviors, AbortSignal pre-abort.tests/dep-graph.test.ts— pins zero non-catalog external deps.tests/tree-shake.test.ts— pinssideEffects: false.
Migration impact
@suaveplan/image has zero current consumers in genesis (it does not yet exist). Downstream packages that will consume it (compress-image, future react-image) will adopt the new API in follow-up changes. No existing code is affected.
Impact
Affected dependents
No dependents (verified by bunx turbo ls --filter=...@suaveplan/image — package does not exist on disk yet).