@konfig.ts/core
@konfig.ts/core is the foundation the other konfig.ts packages are built on. It knows nothing about Kubernetes resource shapes; it provides the machinery that every package shares:
- the manifest carrier that wraps a value to be rendered (
Manifest), - the typed needs and provides that drive compile-time dependency tracking (
Dep), - the module factories that give a build a namespace and a target (
Module), - Helm chart rendering with digest verification (
Helm.release), - deterministic YAML serialization and a structural diff,
- and the
renderentrypoint the CLI calls.
Most projects work with the higher-level packages (@konfig.ts/k8s, @konfig.ts/env, @konfig.ts/argocd) and reach into core directly only for Module.*, Dep.*, and Helm.release.
Install
bun add @konfig.ts/coreUsage
A reusable module that creates a namespace and pulls a digest-verified Helm chart. Module.fixedNs pins the module to one namespace. Application.target (from @konfig.ts/argocd) turns the module into an Argo CD Application handle.
export const definePostgres = Application.module({
namespace: "app",
annotations: Sync.wave(-1),
build: ({ name, namespace }, opts: PostgresOpts) => {
const ns = Namespace.make({ name: namespace })
const release = Helm.release({
repo: "https://charts.bitnami.com/bitnami",
chart: "postgresql",
releaseName: name,
version: "16.0.0",
digest: "sha256:483dc159c5fb377c29026d363153cc904a7f77109d524881eed64098637b9bd4",
namespace,
values: {
auth: {
database: "app",
username: "app",
existingSecret: "db-creds",
secretKeys: {
adminPasswordKey: "password",
userPasswordKey: "password"
}
},
primary: {
persistence: {
enabled: true,
size: `${opts.storageGi}Gi`
}
}
}
})
return [ns, release]
}
})Dependencies between modules are declared inside the build. Writing yield* Dep.Secret("ghcr-pull") records a typed need for that secret; some other module must satisfy it with Dep.provideSecret("ghcr-pull"). Nothing is checked at that point. The check happens when you compose modules at AppOfApps.fromModules; see Dependency graph.
Surface
| Export | Purpose |
|---|---|
Manifest | make, combine, concat, whenever, embedYaml: the Manifest<A> carrier and its combinators |
render, renderManifest, RenderContext | Run a program against a RenderContext (env, cluster, k8s version, flags) and write files |
Dep | Needs (Secret, SecretValues, ConfigMap, Namespace, ServiceAccount, Pvc, Image, Application, App) and provide* layers |
SecretRef, ConfigMapRef, PvcRef, ServiceAccountRef, BuiltImageRef | Branded reference types carried by the needs (BuiltImageRef is also a value with of); *RefName, *RefKeys helpers extract the brand parameters |
Module | fixedNs, dynamicNs factories; Target, BuildContext, LiteralName types |
Bundle, Compose | Non-Argo module composition (Bundle.define, Bundle.target, Bundle.fromModules; Bundle.entrypoint is a deprecated no-op wrapper) and the type-level tracking of unmet needs behind every fromModules (Compose.makeResidualEntrypoint, Compose.NoDuplicateProvides) |
Helm | Helm.release({ repo, chart, version, digest, values, releaseName?, namespace?, extraOpts?, minVersion? }): chart pull, SHA-256 digest verification, helm template |
Yaml | serialize (stable key order) and filenameFor |
diffFiles, formatDiff, hasDifferences, parseYaml, parseYamlAll, deepEqual, redact | Structural YAML diff with Secret data redaction |
KonfigConfig, EnvEntry, OutDir, CrdConfig, HelmConfig, DiffConfig, ServicesConfig, ClusterSpec, decodeKonfigConfigSync, decodeKonfigConfigEffect | Schemas and decoders for konfig.json; ResolvedKonfigConfig pairs the decoded config with its directory |
ImagesConfig, EnvImages, decodeImagesSync, decodeImagesEffect, imagesFor, lookupEnv, lookupEnvEffect, requireImage, requireImageEffect | Schema and lookups for images.json |
boundary, makeStrictDecoder, brand, unsafeCoerce | Schema decode at boundaries; annotated escape hatches |
runProcessString, runProcessExit, processDetail | Subprocess helpers used by Helm and the secret backends |
Errors
Core exports tagged error classes from src/index.ts. The render-time ones are grouped in the AnyRenderError union, which is the error type you see on every manifest’s render and on the fromModules compositions built on top of core.
| Error | Meaning | In AnyRenderError |
|---|---|---|
RenderError | A render step failed; carries a message and an optional cause | yes |
EmbedYamlReadError | Manifest.embedYaml could not read the file at path | yes |
BoundaryDecodeError | Data at a boundary did not match the named schema | yes |
HelmVersionTooLow | The installed helm is older than the required version | yes |
HelmRenderError | helm template failed for the chart and version | yes |
HelmDigestMismatch | The pulled chart’s SHA-256 digest did not match the expected one | yes |
CrdExtractError | Extracting CRDs from a chart failed | yes |
ProcessError | A subprocess exited non-zero; carries the command, exit code, and stderr tail | no |
ImagesEnvMissing | images.json has no entry for the requested env | no |
ImagesAppMissing | images.json has no image for the requested app in that env | no |
Requirements
effect@^4.0.0-rc.111as a peer dependency (Effect 4, release-candidate line).@effect/platform-nodeandyamlare regular dependencies:render()needs the Node filesystem and subprocess services, so they install with the package.- Runtime: Bun recommended; Node >= 23.6 works; Node 22.6 to 23.5 with
--experimental-strip-types;tsxworks.
Source and README: packages/core.