TypeScript SDK for generating Kubernetes manifests with TypeScript instead of Helm templates.
Published as @nelm/chart-ts-sdk. Users import types (RenderContext, RenderResult, etc.)
and the runRender helper to build chart renderers that run under Deno.
Runtime: Deno — uses Deno.args, Deno.readTextFile, Deno.writeTextFile.
Module system: ESM only ("type": "module").
3 source files total. Small, focused SDK.
npm run build # tsup src/index.ts --format esm --dts
npx tsc --noEmit # Type-check only (no emit)
# No linter, formatter, or test framework configured.
# No dev/watch scripts.Build output: dist/index.js (ESM bundle) + dist/index.d.ts (declarations).
Built automatically on prepublishOnly and prepack.
src/
├── index.ts # Barrel re-exports from types/ and utils/
├── types/
│ └── index.ts # All interfaces and type aliases
└── utils/
└── index.ts # runRender() — file I/O, YAML parse/serialize, handler invocation
dist/ and node_modules/ are gitignored.
target: ESNext,module: ESNext,moduleResolution: Bundlerstrict: true (all strict checks enabled)allowJs: false,skipLibCheck: true,resolveJsonModule: trueesModuleInterop: truerootDir: ./src,outDir: ./dist
- Named imports only — no default imports, no namespace imports.
- Relative paths for internal modules:
'../types'(no path aliases). node:prefix for Node.js built-ins:"node:util".- JSR specifiers for Deno std libs:
"@std/yaml". - Prefer single quotes. Prefer semicolons.
// Correct
import {RenderHandler, RenderContext} from '../types';
import {parseArgs} from "node:util";
import {parse, stringify} from "@std/yaml";
// Wrong
import * as types from '../types';
import RenderContext from '../types';- Barrel exports via
index.tsin each directory. - Root
src/index.tsre-exports everything:export * from './types/index'. - All public types/functions MUST flow through the barrel chain.
- New modules: create directory with
index.ts, addexport *in parent barrel.
- PascalCase for interface/type names:
RenderContext,ChartMetadata. - No
Iprefix —Release, notIRelease. - PascalCase properties for Helm/K8s-compatible structures — mirrors Go's exported fields.
- camelCase properties for SDK-internal structures:
manifestsinRenderResult. export interface— always exported.export typefor aliases:export type RenderHandler = ....
// Helm-compatible — PascalCase properties
export interface Release {
Name: string;
Namespace: string;
IsInstall: boolean;
IsUpgrade: boolean;
}
// SDK-internal — camelCase properties
export interface RenderResult {
manifests: object[] | null;
}export const+ arrow for async functions:export const runRender = async (...) => { }.export functionfor synchronous helpers.$is the conventional parameter name forRenderContext.- Explicit return types on exported functions.
| nullin types (not| undefined):manifests: object[] | null.- Nullish coalescing
??for defaults:$.Values.replicaCount ?? 1. - Optional chaining
?.for nested access:$.Values.image?.repository.
- No custom error classes. Errors thrown directly via
new Error(...). - No try/catch in SDK — errors propagate to Deno runtime.
runRendervalidates handler output: throws ifmanifestsis not an array.
| Element | Convention | Example |
|---|---|---|
| Interfaces/Types | PascalCase | RenderContext, RenderResult |
| Helm-compat fields | PascalCase | Release.Name, Chart.Version |
| SDK-internal fields | camelCase | manifests |
| Functions | camelCase | runRender, fullname |
| Variables/params | camelCase | handler, ctx |
| RenderContext param | $ |
function labels($: RenderContext) |
| Directories | lowercase | types/, utils/ |
- async/await preferred over raw Promises.
RenderHandlersupports both sync and async return.
runRender reads YAML input from a file and writes YAML output to a file:
- Parses
--input-fileand--output-filefromDeno.args - Reads input file → deserializes YAML →
RenderContext - Calls handler, validates non-empty
manifestsarray - Serializes manifests to multi-document YAML (joined by
---\n) - Writes to output file
deno run render.ts --input-file context.yaml --output-file manifests.yaml
Do NOT change the file-based I/O contract — it is the IPC mechanism with the Nelm runtime.
- Runtime:
@std/yaml(vianpm:@jsr/std__yaml) — YAML parse/serialize - Dev:
typescript,tsup,@types/node,@types/deno
Keep runtime dependencies minimal. Do not add new ones without explicit approval.
- Create types in
src/types/index.ts(or a new file re-exported from it). - Create utilities in
src/utils/index.ts(or a new file re-exported from it). - Ensure new exports flow through the barrel chain to
src/index.ts. - Run
npx tsc --noEmitto type-check. - Run
npm run buildto verify the bundle.
- Deno runtime: Code runs under Deno, not Node.js.
Deno.*APIs are used directly. - No tests: No test infrastructure exists. If adding, choose a Deno-compatible runner.
- No linter/formatter: Follow conventions in this doc.
- PascalCase properties: Helm-compatible interfaces use Go-style naming. Do not "fix" to camelCase.
@std/yamlis a JSR package: Imported as@std/yaml, resolved via@jsr:registryin.npmrc.