@konfig.ts/k8s 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Branded port name — a string carrying the literal `N` in its type.
3
+ * Constructed by `Port.make({ name, containerPort })` and `Port.ref(name)`.
4
+ * The brand lets probes and Service `targetPort` constrain their
5
+ * `port` field to a member of the container's declared port-name union
6
+ * rather than `string`.
7
+ */
8
+ declare const PortNameBrand: unique symbol;
9
+ export type PortName<N extends string> = string & {
10
+ readonly [PortNameBrand]: N;
11
+ };
12
+ export type ContainerProtocol = "TCP" | "UDP" | "SCTP";
13
+ export interface ContainerPort<N extends string = string> {
14
+ readonly containerPort: number;
15
+ readonly name?: PortName<N>;
16
+ readonly protocol?: ContainerProtocol;
17
+ readonly hostPort?: number;
18
+ readonly hostIP?: string;
19
+ }
20
+ export interface PortInput<N extends string> {
21
+ readonly name: N;
22
+ readonly containerPort: number;
23
+ readonly protocol?: ContainerProtocol;
24
+ readonly hostPort?: number;
25
+ readonly hostIP?: string;
26
+ }
27
+ /**
28
+ * `Port` value namespace.
29
+ *
30
+ * ports: [Port.make({ name: "http", containerPort: 8080 })],
31
+ * readinessProbe: { httpGet: { port: Port.ref("http") } },
32
+ *
33
+ * - `Port.make(input)` constructs a named container port; the literal
34
+ * `name` is captured in the returned `ContainerPort<N>` brand so
35
+ * `Container` can infer the port-name union and constrain
36
+ * cross-references (probes, Service.targetPort).
37
+ * - `Port.ref(name)` returns the brand alone, for probe targets and
38
+ * `targetPort` references that need to name an existing declared port.
39
+ */
40
+ export declare const Port: {
41
+ make: <const N extends string>(input: PortInput<N>) => ContainerPort<N>;
42
+ ref: <const N extends string>(name: N) => PortName<N>;
43
+ };
44
+ export interface HttpHeader {
45
+ readonly name: string;
46
+ readonly value: string;
47
+ }
48
+ export interface HttpGetAction<Ports extends string> {
49
+ readonly path?: string;
50
+ readonly port: number | PortName<Ports>;
51
+ readonly host?: string;
52
+ readonly scheme?: "HTTP" | "HTTPS";
53
+ readonly httpHeaders?: ReadonlyArray<HttpHeader>;
54
+ }
55
+ export interface TcpSocketAction<Ports extends string> {
56
+ readonly port: number | PortName<Ports>;
57
+ readonly host?: string;
58
+ }
59
+ export interface GrpcAction<Ports extends string> {
60
+ readonly port: number | PortName<Ports>;
61
+ readonly service?: string;
62
+ }
63
+ export interface ExecAction {
64
+ readonly command: ReadonlyArray<string>;
65
+ }
66
+ /**
67
+ * Probe target — `port` references on httpGet/tcpSocket/grpc are
68
+ * constrained to `Ports`, the union of names declared on the owning
69
+ * container. A bare number is always accepted; only the named variant
70
+ * is checked.
71
+ */
72
+ export interface ProbeTarget<Ports extends string> {
73
+ readonly httpGet?: HttpGetAction<Ports>;
74
+ readonly tcpSocket?: TcpSocketAction<Ports>;
75
+ readonly grpc?: GrpcAction<Ports>;
76
+ readonly exec?: ExecAction;
77
+ readonly initialDelaySeconds?: number;
78
+ readonly periodSeconds?: number;
79
+ readonly timeoutSeconds?: number;
80
+ readonly successThreshold?: number;
81
+ readonly failureThreshold?: number;
82
+ readonly terminationGracePeriodSeconds?: number;
83
+ }
84
+ export type NamesOf<P extends ReadonlyArray<unknown>> = {
85
+ readonly [K in keyof P]: P[K] extends ContainerPort<infer N> ? N : never;
86
+ }[number];
87
+ /**
88
+ * Service-port input bound to a container's port-name union. `targetPort`
89
+ * accepts a bare number or a `PortName<Ports>`. The `Ports` parameter is
90
+ * locked by `forContainer` on `Service.fromContainer`; use `Port.ref(name)`
91
+ * to reference declared ports.
92
+ */
93
+ export interface ServicePortSpec<Ports extends string> {
94
+ readonly name?: string;
95
+ readonly port: number;
96
+ readonly targetPort: number | PortName<Ports>;
97
+ readonly protocol?: ContainerProtocol;
98
+ readonly appProtocol?: string;
99
+ readonly nodePort?: number;
100
+ }
101
+ export {};
package/dist/refs.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { type ConfigMapRef as CMRef, type PvcRef as PRef, type ServiceAccountRef as SARef, type SecretRef as SRef } from "@konfig.ts/core";
2
+ export type SecretRef<N extends string = string, K extends string = string, Ns extends string = string> = SRef<N, K, Ns>;
3
+ export type ConfigMapRef<N extends string = string, K extends string = string> = CMRef<N, K>;
4
+ export type ServiceAccountRef<N extends string = string> = SARef<N>;
5
+ export type PvcRef<N extends string = string> = PRef<N>;
6
+ export type { ConfigMapRefKeys, ConfigMapRefName, PvcRefName, SecretRefKeys, SecretRefName, } from "@konfig.ts/core";
7
+ export type { SecretRefNamespace } from "@konfig.ts/core";
8
+ export declare const SecretRef: {
9
+ of: <N extends string, K extends string = string, Ns extends string = string>(name: N) => SecretRef<N, K, Ns>;
10
+ /**
11
+ * Escape hatch — widen a typed ref's namespace slot to `any`, making
12
+ * it usable across any pod context. Use sparingly (legitimate
13
+ * cross-namespace cases: ExternalSecret reflection, in-cluster
14
+ * shared infra). The cast is grep-able so PR reviewers see opt-ins.
15
+ */
16
+ unsafeReNamespace: <N extends string, K extends string>(ref: SecretRef<N, K, any>) => SecretRef<N, K, any>;
17
+ };
18
+ export declare const ConfigMapRef: {
19
+ of: <N extends string, K extends string = string>(name: N) => ConfigMapRef<N, K>;
20
+ };
21
+ export declare const ServiceAccountRef: {
22
+ of: <N extends string>(name: N) => ServiceAccountRef<N>;
23
+ };
24
+ export declare const PvcRef: {
25
+ of: <N extends string>(name: N) => PvcRef<N>;
26
+ };
@@ -0,0 +1,36 @@
1
+ import { Dep, type Manifest, RenderError, type SecretRef } from "@konfig.ts/core";
2
+ import type { SecretEntry, SecretSource } from "@konfig.ts/env";
3
+ import { type Context, type Layer } from "effect";
4
+ import type { SecretBackend } from "./backend";
5
+ import { EnvVar } from "./env";
6
+ export interface DeclaredSecret<N extends string, K extends string, Ns extends string = string> {
7
+ readonly ref: SecretRef<N, K, Ns>;
8
+ readonly name: N;
9
+ readonly namespace: Ns;
10
+ readonly keys: ReadonlyArray<K>;
11
+ readonly envVars: ReadonlyArray<EnvVar>;
12
+ readonly manifest?: Manifest.Manifest<unknown>;
13
+ readonly refLayer: Layer.Layer<Dep.Provide<"Secret", N>>;
14
+ readonly values?: Context.Service<Dep.Need<"SecretValues", N>, Dep.SecretValuesRecord<K>>;
15
+ readonly layer?: Layer.Layer<Dep.Provide<"SecretValues", N>, RenderError, Manifest.RenderServices>;
16
+ }
17
+ export interface BindSecretInput<N extends string, K extends string, E extends Readonly<Record<K, string>>, Ns extends string = string> {
18
+ readonly secret: SecretEntry<N, K, E>;
19
+ readonly backend?: SecretBackend<N, K>;
20
+ readonly source?: SecretSource<K, Manifest.RenderServices>;
21
+ readonly labels?: Readonly<Record<string, string>>;
22
+ readonly annotations?: Readonly<Record<string, string>>;
23
+ /**
24
+ * Override the contract's baked-in `namespace` for this bind. Useful
25
+ * when the same `Secret` declaration is consumed across multiple
26
+ * k8s namespaces (e.g. prod / staging / local of the same workload)
27
+ * — the runtime read is namespace-independent, but each binding emits
28
+ * its manifest into a different namespace.
29
+ *
30
+ * When passed as a string literal (via `Environment.bind`'s
31
+ * `const namespace`), the literal flows into the ref's brand so
32
+ * `secretEnvForPod` can enforce cross-namespace coherence.
33
+ */
34
+ readonly namespace?: Ns;
35
+ }
36
+ export declare const bindSecret: <N extends string, K extends string, E extends Readonly<Record<K, string>>, const Ns extends string = string>(input: BindSecretInput<N, K, E, Ns>) => DeclaredSecret<N, K, Ns>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Selector — one source of truth for "this pod set."
3
+ *
4
+ * `Selector<L>` wraps a literal label record and brands it. Resources
5
+ * that *select* pods — Deployment.selector, Service.selector,
6
+ * NetworkPolicy.podSelector, HPA target — take the bundle directly via
7
+ * `Deployment.fromPodSet` / `Service.fromPodSet` / `NetworkPolicy.fromPodSet`
8
+ * so a drift across three resources (the classic "service has no
9
+ * endpoints / netpol denies everything" bug) becomes a compile error.
10
+ *
11
+ * `Workload.web` already keeps these labels coherent internally; the
12
+ * Selector is the win when users go off-script: StatefulSet, DaemonSet,
13
+ * cross-namespace selectors, or wiring a NetworkPolicy from app A to
14
+ * peer pods B.
15
+ */
16
+ declare const SelectorBrand: unique symbol;
17
+ export interface Selector<L extends Readonly<Record<string, string>>> {
18
+ readonly [SelectorBrand]: L;
19
+ readonly labels: L;
20
+ }
21
+ /**
22
+ * `Selector` value namespace.
23
+ *
24
+ * const apiPods = Selector.make({ app: "api", tier: "web" });
25
+ */
26
+ export declare const Selector: {
27
+ make: <const L extends Readonly<Record<string, string>>>(labels: L) => Selector<L>;
28
+ };
29
+ export type SelectorLabels<S> = S extends Selector<infer L> ? L : never;
30
+ export {};
@@ -0,0 +1,108 @@
1
+ import type { ConfigMapRef, PvcRef, SecretRef } from "@konfig.ts/core";
2
+ /**
3
+ * Branded volume name — a string carrying the literal `N` in its
4
+ * phantom. Constructed by the volume factories
5
+ * (`Volume.empty`, `Volume.fromSecret`, …) and `Volume.mountRef`. Lets
6
+ * `VolumeMount<Mounts>` and `Pod` constrain a container's
7
+ * `volumeMounts[i].name` to volumes that the pod actually declares.
8
+ */
9
+ declare const VolumeNameBrand: unique symbol;
10
+ export type VolumeName<N extends string> = string & {
11
+ readonly [VolumeNameBrand]: N;
12
+ };
13
+ export interface Volume<N extends string = string> {
14
+ readonly name: VolumeName<N>;
15
+ readonly secret?: {
16
+ readonly secretName: string;
17
+ readonly optional?: boolean;
18
+ readonly defaultMode?: number;
19
+ };
20
+ readonly configMap?: {
21
+ readonly name: string;
22
+ readonly optional?: boolean;
23
+ readonly defaultMode?: number;
24
+ readonly items?: ReadonlyArray<{
25
+ readonly key: string;
26
+ readonly path: string;
27
+ }>;
28
+ };
29
+ readonly emptyDir?: {
30
+ readonly medium?: string;
31
+ readonly sizeLimit?: string;
32
+ };
33
+ readonly persistentVolumeClaim?: {
34
+ readonly claimName: PvcRef<string>;
35
+ readonly readOnly?: boolean;
36
+ };
37
+ readonly hostPath?: {
38
+ readonly path: string;
39
+ readonly type?: string;
40
+ };
41
+ }
42
+ export interface EmptyVolumeInput<N extends string> {
43
+ readonly name: N;
44
+ readonly medium?: string;
45
+ readonly sizeLimit?: string;
46
+ }
47
+ export interface VolumeFromSecretInput<N extends string> {
48
+ readonly name: N;
49
+ readonly ref: SecretRef<string>;
50
+ readonly optional?: boolean;
51
+ readonly defaultMode?: number;
52
+ }
53
+ export interface VolumeFromConfigMapInput<N extends string> {
54
+ readonly name: N;
55
+ readonly ref: ConfigMapRef<string>;
56
+ readonly optional?: boolean;
57
+ readonly defaultMode?: number;
58
+ readonly items?: ReadonlyArray<{
59
+ readonly key: string;
60
+ readonly path: string;
61
+ }>;
62
+ }
63
+ export interface VolumeFromPvcInput<N extends string, PvcN extends string> {
64
+ readonly name: N;
65
+ readonly claim: PvcRef<PvcN>;
66
+ readonly readOnly?: boolean;
67
+ }
68
+ /**
69
+ * `Volume` value namespace.
70
+ *
71
+ * volumes: [
72
+ * Volume.empty({ name: "config" }),
73
+ * Volume.fromSecret({ name: "tls", ref: tlsSecret.ref }),
74
+ * Volume.fromConfigMap({ name: "settings", ref: cfg.ref }),
75
+ * Volume.fromPvc({ name: "data", claim: pvc.ref }),
76
+ * ],
77
+ * volumeMounts: [
78
+ * { name: Volume.mountRef("config"), mountPath: "/etc/conf" },
79
+ * ],
80
+ *
81
+ * All four constructors capture the literal `name` in the returned
82
+ * `Volume<N>` brand; `Pod` infers the union and constrains each
83
+ * container's `volumeMounts[i].name` to it.
84
+ */
85
+ export declare const Volume: {
86
+ empty: <const N extends string>(input: EmptyVolumeInput<N>) => Volume<N>;
87
+ fromSecret: <const N extends string>(input: VolumeFromSecretInput<N>) => Volume<N>;
88
+ fromConfigMap: <const N extends string>(input: VolumeFromConfigMapInput<N>) => Volume<N>;
89
+ fromPvc: <const N extends string, const PvcN extends string>(input: VolumeFromPvcInput<N, PvcN>) => Volume<N>;
90
+ mountRef: <const N extends string>(name: N) => VolumeName<N>;
91
+ };
92
+ /**
93
+ * Typed container volumeMount. `Mounts` is the union of volume names
94
+ * declared on the surrounding pod; `name` must reference one of them.
95
+ * Bare-number variants don't apply (mounts are always by name).
96
+ */
97
+ export interface VolumeMount<Mounts extends string = string> {
98
+ readonly name: VolumeName<Mounts>;
99
+ readonly mountPath: string;
100
+ readonly readOnly?: boolean;
101
+ readonly subPath?: string;
102
+ readonly subPathExpr?: string;
103
+ readonly mountPropagation?: string;
104
+ }
105
+ export type VolumeNamesOf<V extends ReadonlyArray<Volume<string>>> = {
106
+ readonly [I in keyof V]: V[I] extends Volume<infer N> ? N : never;
107
+ }[number];
108
+ export {};
@@ -0,0 +1,117 @@
1
+ import { Manifest } from "@konfig.ts/core";
2
+ import type { CronJob as K8sCronJob, Deployment as K8sDeployment, Job as K8sJob, StatefulSet as K8sStatefulSet } from "./.generated/k8s-types";
3
+ import type { PodSpecInput } from "./container";
4
+ import type { Selector } from "./selector";
5
+ interface WorkloadMeta {
6
+ readonly name: string;
7
+ readonly namespace: string;
8
+ readonly labels?: Readonly<Record<string, string>>;
9
+ readonly annotations?: Readonly<Record<string, string>>;
10
+ }
11
+ interface SelectorAndTemplate {
12
+ readonly selector: {
13
+ readonly matchLabels: Readonly<Record<string, string>>;
14
+ };
15
+ readonly template: {
16
+ readonly metadata?: {
17
+ readonly labels?: Readonly<Record<string, string>>;
18
+ readonly annotations?: Readonly<Record<string, string>>;
19
+ };
20
+ readonly spec: PodSpecInput;
21
+ };
22
+ }
23
+ export interface DeploymentInput extends WorkloadMeta, SelectorAndTemplate {
24
+ readonly replicas?: number;
25
+ readonly strategy?: unknown;
26
+ readonly revisionHistoryLimit?: number;
27
+ readonly progressDeadlineSeconds?: number;
28
+ readonly minReadySeconds?: number;
29
+ }
30
+ /**
31
+ * Deployment built from a `Selector`. The selector's labels become both
32
+ * the Deployment's `spec.selector.matchLabels` and the pod template's
33
+ * `metadata.labels` — coherent by construction. Drift between selector
34
+ * and template (the classic "service has no endpoints" footgun) is
35
+ * structurally impossible once both consume the same `podSet`.
36
+ */
37
+ export interface DeploymentFromPodSetInput<L extends Readonly<Record<string, string>>> {
38
+ readonly name: string;
39
+ readonly namespace: string;
40
+ readonly labels?: Readonly<Record<string, string>>;
41
+ readonly annotations?: Readonly<Record<string, string>>;
42
+ readonly podSet: Selector<L>;
43
+ readonly replicas?: number;
44
+ readonly template: {
45
+ readonly metadata?: {
46
+ readonly labels?: Readonly<Record<string, string>>;
47
+ readonly annotations?: Readonly<Record<string, string>>;
48
+ };
49
+ readonly spec: PodSpecInput;
50
+ };
51
+ readonly strategy?: unknown;
52
+ readonly revisionHistoryLimit?: number;
53
+ readonly progressDeadlineSeconds?: number;
54
+ readonly minReadySeconds?: number;
55
+ }
56
+ export declare const Deployment: {
57
+ make: (input: DeploymentInput) => Manifest.Manifest<K8sDeployment>;
58
+ fromPodSet: <L extends Readonly<Record<string, string>>>(input: DeploymentFromPodSetInput<L>) => Manifest.Manifest<K8sDeployment>;
59
+ };
60
+ export interface StatefulSetInput extends WorkloadMeta, SelectorAndTemplate {
61
+ readonly replicas?: number;
62
+ readonly serviceName: string;
63
+ readonly volumeClaimTemplates?: ReadonlyArray<unknown>;
64
+ readonly podManagementPolicy?: string;
65
+ readonly updateStrategy?: unknown;
66
+ }
67
+ export declare const StatefulSet: {
68
+ make: (input: StatefulSetInput) => Manifest.Manifest<K8sStatefulSet>;
69
+ };
70
+ export interface JobInput extends WorkloadMeta {
71
+ readonly parallelism?: number;
72
+ readonly completions?: number;
73
+ readonly backoffLimit?: number;
74
+ readonly activeDeadlineSeconds?: number;
75
+ readonly ttlSecondsAfterFinished?: number;
76
+ readonly suspend?: boolean;
77
+ readonly template: {
78
+ readonly metadata?: {
79
+ readonly labels?: Readonly<Record<string, string>>;
80
+ readonly annotations?: Readonly<Record<string, string>>;
81
+ };
82
+ readonly spec: PodSpecInput;
83
+ };
84
+ }
85
+ export declare const Job: {
86
+ make: (input: JobInput) => Manifest.Manifest<K8sJob>;
87
+ };
88
+ export interface CronJobInput extends WorkloadMeta {
89
+ readonly schedule: string;
90
+ readonly concurrencyPolicy?: string;
91
+ readonly successfulJobsHistoryLimit?: number;
92
+ readonly failedJobsHistoryLimit?: number;
93
+ readonly startingDeadlineSeconds?: number;
94
+ readonly suspend?: boolean;
95
+ readonly jobTemplate: {
96
+ readonly metadata?: {
97
+ readonly labels?: Readonly<Record<string, string>>;
98
+ readonly annotations?: Readonly<Record<string, string>>;
99
+ };
100
+ readonly spec: {
101
+ readonly template: {
102
+ readonly metadata?: {
103
+ readonly labels?: Readonly<Record<string, string>>;
104
+ readonly annotations?: Readonly<Record<string, string>>;
105
+ };
106
+ readonly spec: PodSpecInput;
107
+ };
108
+ readonly backoffLimit?: number;
109
+ readonly activeDeadlineSeconds?: number;
110
+ readonly ttlSecondsAfterFinished?: number;
111
+ };
112
+ };
113
+ }
114
+ export declare const CronJob: {
115
+ make: (input: CronJobInput) => Manifest.Manifest<K8sCronJob>;
116
+ };
117
+ export {};
@@ -0,0 +1,97 @@
1
+ import type { Manifest, SecretRef } from "@konfig.ts/core";
2
+ import type { CronJob as K8sCronJob, Deployment as K8sDeployment, Ingress as K8sIngress, IngressRule as K8sIngressRule, Service as K8sService, ServiceAccount as K8sServiceAccount } from "./.generated/k8s-types";
3
+ import type { ContainerInput, ContainerSpec } from "./container";
4
+ import { type IngressTLSInput } from "./network";
5
+ import type { ServicePortSpec } from "./ports";
6
+ import type { Volume } from "./volume";
7
+ /**
8
+ * Union of port names declared by every `ContainerSpec` in `Cs`. Raw
9
+ * `ContainerInput` entries (no `Container.define`) contribute `never`,
10
+ * so untyped containers don't widen the result — they just don't add
11
+ * any named-port options to the Service. With every container untyped,
12
+ * the union collapses to `never` and `targetPort` is effectively
13
+ * `number`-only, matching Kubernetes' behaviour when no port is named.
14
+ */
15
+ type _PortNamesOfContainers<Cs extends ReadonlyArray<ContainerInput>> = {
16
+ readonly [K in keyof Cs]: Cs[K] extends ContainerSpec<infer P, string> ? P : never;
17
+ }[number];
18
+ /**
19
+ * Reloader integration shorthand. Two complementary rotation models:
20
+ *
21
+ * - *Build-time* rotation (re-render → new hash → rolling update). konfig
22
+ * does NOT stamp this automatically; it ships `hashSecretValues` as a
23
+ * helper you attach yourself — feed it your resolved secret values and
24
+ * place the digest into `deployment.podAnnotations`, so a value change
25
+ * flips the pod template and triggers a rollout.
26
+ * - *Runtime* rotation via Stakater's Reloader (operator watches mounted
27
+ * Secrets/ConfigMaps and patches the workload to restart pods on change),
28
+ * selected by the option below.
29
+ *
30
+ * Pick:
31
+ *
32
+ * - `"off"` (default) — no Reloader annotation. Pair with a build-time
33
+ * `hashSecretValues` annotation if you accept the redeploy-on-edit model.
34
+ * - `"stakater"` — emit `reloader.stakater.com/auto: "true"`. Reloader
35
+ * watches every Secret/ConfigMap referenced by the pod spec.
36
+ * - `"stakater-strict"` — emit `reloader.stakater.com/auto: "true"`
37
+ * plus `reloader.stakater.com/match: "true"`, restricting watch
38
+ * to objects with the matching annotation set on them.
39
+ * - `{ secrets, configMaps }` — explicit per-resource lists, emitted
40
+ * as `secret.reloader.stakater.com/reload` /
41
+ * `configmap.reloader.stakater.com/reload` (comma-joined).
42
+ *
43
+ * See packages/k8s/README.md for the trade-off between build-time
44
+ * hashes and runtime reloader.
45
+ */
46
+ export type ReloaderOption = "off" | "stakater" | "stakater-strict" | {
47
+ readonly secrets?: ReadonlyArray<string>;
48
+ readonly configMaps?: ReadonlyArray<string>;
49
+ };
50
+ interface WebInput<Cs extends ReadonlyArray<ContainerInput>> {
51
+ readonly name: string;
52
+ readonly namespace: string;
53
+ readonly labels?: Readonly<Record<string, string>>;
54
+ readonly annotations?: Readonly<Record<string, string>>;
55
+ /** Pod-restart-on-rotation integration. See `ReloaderOption`. */
56
+ readonly reloader?: ReloaderOption;
57
+ readonly deployment: {
58
+ readonly replicas?: number;
59
+ readonly containers: Cs;
60
+ readonly volumes?: ReadonlyArray<Volume>;
61
+ readonly imagePullSecrets?: ReadonlyArray<{
62
+ readonly name: SecretRef<string>;
63
+ }>;
64
+ readonly serviceAccountName?: string;
65
+ readonly podLabels?: Readonly<Record<string, string>>;
66
+ readonly podAnnotations?: Readonly<Record<string, string>>;
67
+ };
68
+ readonly service: {
69
+ readonly ports: ReadonlyArray<ServicePortSpec<NoInfer<_PortNamesOfContainers<Cs>>>>;
70
+ readonly type?: "ClusterIP" | "NodePort" | "LoadBalancer";
71
+ };
72
+ readonly ingress?: {
73
+ readonly ingressClassName?: string;
74
+ readonly rules?: ReadonlyArray<K8sIngressRule>;
75
+ readonly tls?: ReadonlyArray<IngressTLSInput>;
76
+ readonly annotations?: Readonly<Record<string, string>>;
77
+ };
78
+ }
79
+ export declare const web: <const Cs extends ReadonlyArray<ContainerInput>>(input: WebInput<Cs>) => Manifest.Manifest<readonly [K8sDeployment, K8sService] | readonly [K8sDeployment, K8sService, K8sIngress]>;
80
+ interface CronInput {
81
+ readonly name: string;
82
+ readonly namespace: string;
83
+ readonly schedule: string;
84
+ readonly labels?: Readonly<Record<string, string>>;
85
+ readonly annotations?: Readonly<Record<string, string>>;
86
+ readonly concurrencyPolicy?: "Allow" | "Forbid" | "Replace";
87
+ readonly successfulJobsHistoryLimit?: number;
88
+ readonly failedJobsHistoryLimit?: number;
89
+ readonly containers: ReadonlyArray<ContainerInput>;
90
+ readonly volumes?: ReadonlyArray<Volume>;
91
+ readonly imagePullSecrets?: ReadonlyArray<{
92
+ readonly name: SecretRef<string>;
93
+ }>;
94
+ readonly restartPolicy?: "OnFailure" | "Never";
95
+ }
96
+ export declare const cron: (input: CronInput) => Manifest.Manifest<readonly [K8sServiceAccount, K8sCronJob]>;
97
+ export {};
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@konfig.ts/k8s",
3
+ "version": "0.0.1",
4
+ "description": "Kubernetes resource builders (workloads, network, identity, policy, volume, env) for konfig.ts.",
5
+ "license": "MIT",
6
+ "author": "David Stahl-Gruber",
7
+ "homepage": "https://github.com/DwieDave/konfig.ts#readme",
8
+ "bugs": "https://github.com/DwieDave/konfig.ts/issues",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/DwieDave/konfig.ts.git",
12
+ "directory": "packages/k8s"
13
+ },
14
+ "keywords": [
15
+ "kubernetes",
16
+ "k8s",
17
+ "config",
18
+ "effect",
19
+ "typescript"
20
+ ],
21
+ "type": "module",
22
+ "sideEffects": false,
23
+ "main": "./dist/index.mjs",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.mjs"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "engines": {
37
+ "node": ">=20"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "scripts": {
43
+ "build": "tsdown ./src/index.ts --format=esm --target=node20 --sourcemap --clean --no-dts && tsc -p tsconfig.build.json",
44
+ "check": "tsc -p tsconfig.check.json --noEmit",
45
+ "test": "vitest run",
46
+ "lint": "oxlint",
47
+ "lint:apply": "oxlint --fix",
48
+ "prepublishOnly": "bun run build",
49
+ "prepack": "node ../../scripts/prepack-exports.mjs strip",
50
+ "postpack": "node ../../scripts/prepack-exports.mjs restore"
51
+ },
52
+ "dependencies": {
53
+ "@konfig.ts/core": "0.0.1",
54
+ "@konfig.ts/env": "0.0.1",
55
+ "kubernetes-types": "~1.30.0"
56
+ },
57
+ "peerDependencies": {
58
+ "effect": "4.0.0-beta.70"
59
+ },
60
+ "devDependencies": {
61
+ "@effect/platform-node": "catalog:",
62
+ "@effect/vitest": "catalog:",
63
+ "@types/bun": "catalog:",
64
+ "effect": "catalog:",
65
+ "fast-check": "catalog:",
66
+ "typescript": "catalog:",
67
+ "vitest": "catalog:"
68
+ }
69
+ }