You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make the whole @freelensapp/kube-object type surface reachable through @freelensapp/extensions, so extensions no longer need it as a direct dependency.
Surfaced while checking the real extensions against the dependency audit in #2360
(comment).
Why
The v2 packaging contract (#2304, D4/D5) says @freelensapp/extensions is the only
published package and every other @freelensapp/* is private and must not be a direct
dependency of an extension. Today that contract cannot be honoured: both maintained
extensions import types straight from @freelensapp/kube-object, and those types are not
re-exported by the API.
Extension
Files importing @freelensapp/kube-object
Types used
freelens-fluxcd-extension 5.3.1
41
LocalObjectReference
freelens-gateway-api-extension 0.2.1
4
Condition, LabelSelector, ObjectReference
These are plain building blocks for describing CRD specs — exactly what an extension that
adds resource views needs. All four exist today:
@freelensapp/kube-object is published on npm at 1.10.3 (2026-07-07), from the v1 era
where @freelensapp/core was itself a real dependency of every extension. In v2 the
package goes private, so unless the API re-exports it, both of these extensions are
blocked from porting.
Scope of the gap
@freelensapp/kube-object exports 419 top-level symbols. extensions/common-api/k8s-api.ts re-exports 55 of them, so 364 are missing —
including the four above. The re-exported set is essentially the concrete kube objects
(Pod, Deployment, Secret, …), KubeObject, KubeObjectMetadata, OwnerReference
and the JSON-API guards; what is missing is most of the shared spec vocabulary
(Affinity, Capabilities, ContainerPort, Probe, ResourceRequirements, SecurityContext, Toleration, the types/ directory in general).
Picking symbols one by one as extensions ask for them does not scale. A blanket export * from "@freelensapp/kube-object" in the K8sApi namespace is the obvious fix.
There is exactly one name collision
A collision check across common-api/k8s-api.ts, renderer-api/k8s-api.ts and main-api/k8s-api.ts against all 419 names finds a single clash — and it is a real one,
two different types sharing a name:
// packages/kube-object/src/api-types.ts:287 — a Kubernetes resource status shapeexportinterfaceKubeObjectStatus{conditions?: BaseKubeObjectCondition[];}// packages/core/src/common/k8s-api/kube-object-status.ts:7 — the extension-facing// status registration type, exported today via renderer-api/k8s-api.ts:188exportinterfaceKubeObjectStatus{level: KubeObjectStatusLevel;text: string;timestamp?: string;}
The second one is the v1 Renderer.K8sApi.KubeObjectStatus that extensions register status
providers against, so it must keep the bare name. The kube-object one needs a rename or an
explicit exclusion from the star export.
The same gap exists in @freelensapp/kube-api, in a subtler form
kube-object is the visible case because extensions import from it directly. kube-api
has the same problem one level down: the API exports the things, but not the types that
appear in their own signatures.
@freelensapp/kube-api exports 81 symbols; the API re-exports 34 of them (the concrete *Api classes). What is exported as a usable value but whose parameter types are not
nameable:
Exported by the API
Its signature needs
Nameable by an extension?
KubeApi (local alias)
KubeApiOptions & ExternalKubeApiOptions
ExternalKubeApiOptions yes, KubeApiOptions no
PodsApi, NodesApi, …
DerivedKubeApiOptions
no
KubeObjectStore
KubeObjectStoreOptions
no
Also missing and plausibly wanted by anyone writing CRD support: IKubeWatchEvent, KubeApiListOptions, DeleteOptions, PropagationPolicy, ResourceDescriptor, KubeApiQueryParams, parseKubeApi, createKubeApiURL.
Because the workspace packages are private and inlined, these declarations are physically
present in the bundled d.ts (rollup-plugin-dts inlines whatever the exported declarations
reference) but they are not exported from it. An author can call the API and rely on
contextual typing for an inline object literal, yet cannot write const opts: Renderer.K8sApi.KubeApiOptions<MyObject> = {...} or type a variable holding one. The
escape hatch is ConstructorParameters<typeof Renderer.K8sApi.KubeApi>[0], which is not a
reasonable thing to ask of extension authors.
Neither maintained extension hits this today: both freelens-fluxcd-extension and freelens-gateway-api-extension declare their CRD APIs as empty subclasses
(export class GatewayClassApi extends Renderer.K8sApi.KubeApi<GatewayClass> {}) and never
pass options, so they never need to name an option type. The gap is latent, not blocking —
but it is the same defect, and the fix is the same.
Tasks
Add export * from "@freelensapp/kube-object" to the K8sApi namespace, resolving
the KubeObjectStatus clash (rename the kube-object one on export, or keep an
explicit exclusion list — decide which reads better in the d.ts).
Drop the now-redundant explicit re-export block in common-api/k8s-api.ts, keeping
only the deliberate v1-compat aliases (SecretReference as ISecretRef, PodContainerStatus as IPodContainerStatus, …).
Verify against both extensions that dropping their direct @freelensapp/kube-object
dependency still type-checks.
Do the same for @freelensapp/kube-api: export the option and descriptor types that
appear in already-exported signatures (KubeApiOptions, DerivedKubeApiOptions, KubeObjectStoreOptions, IKubeWatchEvent, KubeApiListOptions, DeleteOptions, PropagationPolicy, ResourceDescriptor, KubeApiQueryParams), plus parseKubeApi
and createKubeApiURL.
Add a check that no exported signature references a type the bundle does not also
export — this class of gap is mechanical and should not depend on someone noticing.
Star-exporting 419 symbols enlarges the public API surface considerably, and everything
in it becomes something the v2 spec promises. That is the intended trade — the
alternative is extension authors depending on a private package — but the symbols are
worth a skim for anything that should stay internal.
Adding Condition and ObjectReference as top-level names in K8sApi may shadow
same-named local types in existing extensions. Type-only, so the failure mode is a
compile error in the extension, not a runtime break — but it belongs in the migration
notes.
Goal
Make the whole
@freelensapp/kube-objecttype surface reachable through@freelensapp/extensions, so extensions no longer need it as a direct dependency.Surfaced while checking the real extensions against the dependency audit in #2360
(comment).
Why
The v2 packaging contract (#2304, D4/D5) says
@freelensapp/extensionsis the onlypublished package and every other
@freelensapp/*is private and must not be a directdependency of an extension. Today that contract cannot be honoured: both maintained
extensions import types straight from
@freelensapp/kube-object, and those types are notre-exported by the API.
@freelensapp/kube-objectfreelens-fluxcd-extension5.3.1LocalObjectReferencefreelens-gateway-api-extension0.2.1Condition,LabelSelector,ObjectReferenceThese are plain building blocks for describing CRD specs — exactly what an extension that
adds resource views needs. All four exist today:
@freelensapp/kube-objectis published on npm at 1.10.3 (2026-07-07), from the v1 erawhere
@freelensapp/corewas itself a real dependency of every extension. In v2 thepackage goes private, so unless the API re-exports it, both of these extensions are
blocked from porting.
Scope of the gap
@freelensapp/kube-objectexports 419 top-level symbols.extensions/common-api/k8s-api.tsre-exports 55 of them, so 364 are missing —including the four above. The re-exported set is essentially the concrete kube objects
(
Pod,Deployment,Secret, …),KubeObject,KubeObjectMetadata,OwnerReferenceand the JSON-API guards; what is missing is most of the shared spec vocabulary
(
Affinity,Capabilities,ContainerPort,Probe,ResourceRequirements,SecurityContext,Toleration, thetypes/directory in general).Picking symbols one by one as extensions ask for them does not scale. A blanket
export * from "@freelensapp/kube-object"in theK8sApinamespace is the obvious fix.There is exactly one name collision
A collision check across
common-api/k8s-api.ts,renderer-api/k8s-api.tsandmain-api/k8s-api.tsagainst all 419 names finds a single clash — and it is a real one,two different types sharing a name:
The second one is the v1
Renderer.K8sApi.KubeObjectStatusthat extensions register statusproviders against, so it must keep the bare name. The kube-object one needs a rename or an
explicit exclusion from the star export.
The same gap exists in
@freelensapp/kube-api, in a subtler formkube-objectis the visible case because extensions import from it directly.kube-apihas the same problem one level down: the API exports the things, but not the types that
appear in their own signatures.
@freelensapp/kube-apiexports 81 symbols; the API re-exports 34 of them (the concrete*Apiclasses). What is exported as a usable value but whose parameter types are notnameable:
KubeApi(local alias)KubeApiOptions & ExternalKubeApiOptionsExternalKubeApiOptionsyes,KubeApiOptionsnoPodsApi,NodesApi, …DerivedKubeApiOptionsKubeObjectStoreKubeObjectStoreOptionsAlso missing and plausibly wanted by anyone writing CRD support:
IKubeWatchEvent,KubeApiListOptions,DeleteOptions,PropagationPolicy,ResourceDescriptor,KubeApiQueryParams,parseKubeApi,createKubeApiURL.Because the workspace packages are private and inlined, these declarations are physically
present in the bundled d.ts (rollup-plugin-dts inlines whatever the exported declarations
reference) but they are not exported from it. An author can call the API and rely on
contextual typing for an inline object literal, yet cannot write
const opts: Renderer.K8sApi.KubeApiOptions<MyObject> = {...}or type a variable holding one. Theescape hatch is
ConstructorParameters<typeof Renderer.K8sApi.KubeApi>[0], which is not areasonable thing to ask of extension authors.
Neither maintained extension hits this today: both
freelens-fluxcd-extensionandfreelens-gateway-api-extensiondeclare their CRD APIs as empty subclasses(
export class GatewayClassApi extends Renderer.K8sApi.KubeApi<GatewayClass> {}) and neverpass options, so they never need to name an option type. The gap is latent, not blocking —
but it is the same defect, and the fix is the same.
Tasks
export * from "@freelensapp/kube-object"to theK8sApinamespace, resolvingthe
KubeObjectStatusclash (rename the kube-object one on export, or keep anexplicit exclusion list — decide which reads better in the d.ts).
common-api/k8s-api.ts, keepingonly the deliberate v1-compat aliases (
SecretReference as ISecretRef,PodContainerStatus as IPodContainerStatus, …).@freelensapp/kube-objectstill inlines into the bundledextension-api.d.tsrather than becoming a declared dependency — it is a privateworkspace package and
rollup.dts.config.mjsmaps every@freelensapp/*specifierto its emitted declarations. Blocked on @freelensapp/extensions build:dist is broken: TypeScript 7 removed the JS compiler API #2363.
@freelensapp/kube-objectdependency still type-checks.
@freelensapp/kube-api: export the option and descriptor types thatappear in already-exported signatures (
KubeApiOptions,DerivedKubeApiOptions,KubeObjectStoreOptions,IKubeWatchEvent,KubeApiListOptions,DeleteOptions,PropagationPolicy,ResourceDescriptor,KubeApiQueryParams), plusparseKubeApiand
createKubeApiURL.export — this class of gap is mechanical and should not depend on someone noticing.
migration guide that
@freelensapp/kube-objectimports move to the API namespace.Risk notes
in it becomes something the v2 spec promises. That is the intended trade — the
alternative is extension authors depending on a private package — but the symbols are
worth a skim for anything that should stay internal.
ConditionandObjectReferenceas top-level names inK8sApimay shadowsame-named local types in existing extensions. Type-only, so the failure mode is a
compile error in the extension, not a runtime break — but it belongs in the migration
notes.
Found via #2360. Contract lives in #2304.