Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1.9 KiB
ADR 002: extractJsonData() Pattern for KubeObject Unwrapping
Status: Accepted
Date: 2026-03-05
Deciders: Development Team
Context
Headlamp's useList() hooks return arrays of KubeObject class instances that wrap raw JSON under .jsonData. The plugin's type system defines plain TypeScript interfaces (e.g., CephCluster, StorageClass) matching the raw Kubernetes JSON structure.
To use these typed interfaces, the KubeObject wrapper must be unwrapped. This pattern appears in every plugin that uses useList() hooks.
Decision
Implement an extractJsonData() utility function that takes a KubeObject instance and returns the unwrapped .jsonData property.
- Apply this consistently to all
useList()results before storing in context state. - All type guards (e.g.,
isRookCephProvisioner(),isRookCephStorageClass()) operate on the unwrapped plain objects, not onKubeObjectwrappers.
Consequences
- ✅ Clean separation between Headlamp's class instances and the plugin's typed interfaces
- ✅ Type guards work on plain objects, which are easier to test
- ✅ Consistent unwrapping pattern across all resources
- ⚠️ Extra mapping step on every
useList()result - ⚠️ Runtime cost of mapping arrays (negligible for typical cluster sizes of tens to hundreds of resources)
Alternatives Considered
-
Use
KubeObjectinstances directly — Rejected. Type guards and filters become harder to write and test with class wrappers. -
Type assertion (
as CephCluster) — Rejected. Unsafe with no runtime validation; silently masks shape mismatches. -
Custom hook wrapping
useList()with auto-extraction — Considered butextractJsonData()is simpler and more explicit. A wrapper hook would hide the unwrapping step, making the data flow less obvious.
Changelog
- 2026-03-05: Initial decision accepted