@konfig.ts/k8s
@konfig.ts/k8s builds Kubernetes resources in TypeScript, with one twist: wherever a resource points at another resource, it takes a branded reference instead of a raw string. An env var that reads from a Secret, a volume that mounts a ConfigMap, an Ingress TLS block that names a Secret, an imagePullSecrets entry: each of these needs a reference produced by the resource it points at. A workload that references a Secret nobody creates is therefore a compile error, not a failed argocd sync. The package also hosts Environment.bind and Secret.bind, the step that takes an environment contract from @konfig.ts/env and turns it into a Deployment env block plus whatever custom resources the chosen secret backend emits.
Install
bun add @konfig.ts/k8sUsage
The API module of the full-stack example. It binds the env contract, defines a container whose env mixes the bound vars with a Secret key and a ConfigMap key, and wraps the container in Workload.web, which produces a Deployment and a Service.
const apiContainer = Container.define({
name,
image: apiImage,
ports: [Port.make({ name: "http", containerPort: 8080 })],
env: [
...bound.envVars,
...EnvVar.secretEnv(bound.members.db.ref, { DATABASE_URL_PRIMARY: "url" }, { podNamespace: namespace }),
...EnvVar.configMapEnv(featureFlags.ref, { FEATURE_NEW_UI: "NEW_UI" }),
EnvVar.value({ name: "API_NAME", value: name })
],
readinessProbe: {
httpGet: { path: "/healthz", port: Port.ref("http") },
periodSeconds: 5
}
})
const workload = Workload.web({
name,
namespace,
deployment: {
replicas: opts.replicas,
imagePullSecrets: [{ name: ghcrRef }],
containers: [apiContainer]
},
service: {
ports: [{ port: 80, targetPort: Port.ref("http") }]
}
})Two of the type-level checks are visible here. EnvVar.fromSecretForPod requires podNamespace to match the Secret’s namespace, so a pod cannot read a Secret from another namespace. Port.ref("http") only accepts a name that was declared in ports, so a probe or Service cannot point at a port that does not exist.
Surface
| Export | Purpose |
|---|---|
Container, Pod, PodSet | Container.define, pod specs, and shared pod-set inputs for workloads |
Port | Port.make({ name, containerPort }), Port.ref(name) for probes and Services |
EnvVar | value, secretEnv, configMapEnv, fromSecret, fromSecretForPod, fromConfigMap, raw; duplicate names in one container are a compile error at Container.define |
Secret, ConfigMap, Namespace, ServiceAccount | Identity constructors exposing a typed .ref; Secret also carries Secret.define and Secret.bind |
Environment | Environment.define re-exported with bind (manifest side) and runtime (process side) |
NativeSecret | NativeSecret.backend({ type?, immutable?, silenceWarning? }): built-in backend that emits a plain Secret from a source |
Workload | Workload.web (Deployment + Service + optional Ingress, reloader: "stakater"), Workload.cron (CronJob + ServiceAccount) |
Deployment, StatefulSet, Job, CronJob, Service, Ingress | Lower-level resource constructors |
Role, RoleBinding, ClusterRole, ClusterRoleBinding, NetworkPolicy, PersistentVolume, PersistentVolumeClaim | RBAC, policy, and storage constructors |
Volume, Selector | Typed volumes/mounts; label selectors shared between workloads and NetworkPolicy peers |
SecretRef, ConfigMapRef, PvcRef, ServiceAccountRef | Brand constructors; SecretRefName, ConfigMapRefName, PvcRefName type helpers |
hashSecretValues | Stamp a pod-spec hash so pods roll on re-render |
SecretBackend, BackendEmitInput, BackendTag | The contract secret backend packages implement |
K8s | Raw Kubernetes types (kubernetes-types@1.30) |
Errors
This package exports no tagged error classes of its own. When a bind or render fails, the error comes from one of two places: the secret backend in use (@konfig.ts/sops, @konfig.ts/sealed-secrets), or @konfig.ts/env, which raises SecretSourceError when a plaintext source cannot be resolved and EnvNameCollision when two entries claim the same env var name.
Requirements
effect@^4.0.0-rc.111as a peer dependency (Effect 4, release-candidate line).- Depends on
@konfig.ts/core,@konfig.ts/env, andkubernetes-types. - Runtime: Bun recommended; Node >= 23.6 works; Node 22.6 to 23.5 with
--experimental-strip-types;tsxworks.
Source and README: packages/k8s.