CLIKontract

How to

Generate contracts

Generate configured contract artifacts from schema sources.

What changes

generate turns configured API schemas, async schemas, and shared schema sources into validation schemas, DTOs, runtime metadata, SDK helpers, message contracts, and other target-specific artifacts.

When this helps

  • A schema source changed and generated artifacts must be refreshed.
  • A target needs regeneration after config changes.
  • You need to clean selected output before a reliable regeneration.

Run this command

terminal
sumr kontract generate --source platform# one sourcesumr kontract generate --source platform --target api-nestjs# one targetsumr kontract generate --clean# preflight before cleaning selected outputs

Flags you can use

--source <name>

Generate only one configured source.

--target <name>

Generate only one configured target.

-c, --concurrency <n>

Limit how many generators run in parallel.

-s, --specific <name>

Generate only schemas matching this name.

--clean

Repeat the write-free configured-generator preflight, then delete selected outputs and the Kontract cache before generation.

--verbose

Show detailed generation output.

--quiet

Suppress all output except errors.

--help, -h

Show the command syntax, supported flags, and examples without changing files.

Keep in mind

  • Do not hand-edit generated contract output. Edit the owning schema source and regenerate.
  • Kontract expands authoring-only kontract.sets / $sets; normalized generated input does not keep those keys.
  • Operation x-kontract-audiences metadata can drive generator.audiences.exclude. Kontract checks each excluded token once against the complete selected OpenAPI source/target universe, not per generated service. Sibling services without a matching audience generate normally; a token absent from the whole source fails validation and the generate --clean preflight before selected output or cache is deleted.
  • On a typescript-nestjs target, operationContract: true emits http/operations.ts and requires dto: zod, dto: class-validator, or dto: both. Each standard JSON controller route uses exactly one generated @ContractOperation(Operation) decorator: it invokes native nestjs-zod ZodResponse runtime metadata and preserves the handler return constraint. The public @sumrco/cli/eslint rule rejects redundant @ZodResponse and @ZodSerializerDto decorators.
  • The NestJS ESLint rule resolves direct http/operations imports and generated http/index.ts directory barrels. Route matching supports @Controller({ path, version }), method @Version() overrides, VERSION_NEUTRAL, and the generated target default for URI versioning.
  • NestJS DTO output uses explicit dto: none, dto: zod, dto: class-validator, or dto: both. zod: true independently emits framework-neutral Zod schemas; dto: zod or dto: both emits Zod DTO constructors. Deprecated Boolean dtos and Boolean dto remain accepted: true with zod: true normalizes to both, true without Zod to class-validator, false with zod: true to zod, and false without Zod to none. Do not combine an explicit string dto mode with dtos; configuration validation rejects it.
  • OpenAPI object schemas are open when additionalProperties is omitted. Kontract preserves that contract with top-level and nested index signatures in generated models and class-validator DTOs so DTOs remain structurally assignable to their models. Those signatures are TypeScript-only: ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }) still rejects undeclared keys. Add additionalProperties: false to a request schema when the runtime API boundary must be closed.
  • NestJS controller generation reuses one normalized transport classifier across controllers, lint metadata, runtime descriptors, and test manifests; operation provenance includes its source JSON Pointer. Controllers may bind each path, query, header, or cookie separately through ContractParameterPipe, or bind a complete non-empty group through its generated operation-owned type and ContractParameterBagPipe(Operation, location). The ESLint rule requires exact generated primitive, optional, array, and aggregate type identities, while enum component references retain their generated enum identity.
  • Generated parameter pipes convert only schema-declared boolean, integer, number, and array wire strings before Zod validation. Aggregate query/path bags reject unknown keys, header lookup is case-insensitive, header/cookie bags select only operation-owned fields, and cookie parsing remains application-owned. Unsupported object parameters, cookie arrays, and styles fail generation. Supported cookies remain in cleaned live Swagger metadata; cleanupOpenApiDoc() restores exact operation-owned parameter schemas after Nest reflection, including array item constraints and cookies.
  • NestJS adoption is opt-in: foundation: true emits exactly one target-wide shared/http/foundation.ts with the only ContractModule, canonical exception filter, and DI-preserving global providers, including ZodSerializerInterceptor. Each service http/foundation.ts is a facade that re-exports that boundary and retains only service-specific buildOpenApiConfig() and cleanupOpenApiDoc(). controllers: true adds thin controller/port/module adapters, while errors, mappers, tests, and bruno add their corresponding generated artifacts. Only JSON operation decorators install serialization metadata; no-content, file, stream, SSE, and raw transports do not. Invalid prerequisite combinations fail before generation.
  • Foundation preflight requires a documented compatible 400 response for validated input, 403 for fail-closed security, 415 for declared request media enforcement, and 500 for JSON output or unexpected failures. One compatible default error response may cover these statuses; generation fails before an undeclared boundary error can be rendered as a misleading 500.
  • The default generated error policy is flat. Nested or otherwise custom documented error contracts must configure the complete errorEnvelope projection, including bodyKey, required outer staticFields, and core status/message/type/code/details keys. sumr kontract validate runs this configured NestJS generator preflight without writes; sumr kontract generate --clean repeats it before deleting selected output or cache.
  • Required request bodies enforce a declared Content-Type through the documented 415 contract. Constant or single-enum response headers become generated @Header decorators; dynamic values remain application-owned. CONTRACT_ERROR_OBSERVER receives only redacted operation, provenance, category, status, and schema diagnostics—never the raw error, message, Zod input, or payload.
  • Structured envelope and errorEnvelope settings project fields from documented success and error schemas; they do not replace schemas or invent application values. Success handlers keep bare payload types, optional metadata is emitted only for schemas that declare it, and unexpected errors stay redacted. Request-derived envelope context requires foundation: true; errorEnvelope requires errors: true. envelopeDataKey is deprecated compatibility syntax for envelope.dataKey and cannot be combined with envelope.
  • NestJS multipart generation supports component-backed single-file, bounded multi-file, named-file, and mixed-field request bodies. There is no multipart flag: framework: express (the default) or framework: fastify selects the adapter. Every binary file requires a positive maxLength; file arrays and repeated non-file arrays also require a positive maxItems.
  • Generated Express controllers require @nestjs/platform-express. Generated Fastify controllers use a buffered @fastify/multipart runtime and require @nestjs/platform-fastify, fastify, and @fastify/multipart; generated multipart adapters are not streaming upload APIs. dto: class-validator and dto: both require class-transformer and class-validator, while tests: true requires @nestjs/testing and supertest. These packages belong to the consuming application or isolated consumer matrix, never Kontract's root package.json.
  • Kontract release checks compile and execute both adapters in a pinned NestJS 11 Docker consumer matrix. Generated-consumer packages—including NestJS, Swagger, RxJS, nestjs-zod, Fastify, class-validator, multipart, and test packages—stay in the consuming project or isolated technology/version matrix rather than Kontract's root package.json, preventing one target's peer versions from changing another target's dependency graph.
  • With tests: true, named-example validation resolves inline examples and local #/components/examples/* references. An externalValue example fails deterministic generation instead of bypassing validation.
  • For typed JSON responses, standalone typescript-fetch clients call a consumer-owned decodeJson(value, operationId) function. Standalone targets do not emit Zod schemas or an operation decoder registry; Axios and Angular currently trust only their TypeScript response generic.
  • With runtime: true, generated toContract structurally validates already-contract-shaped values, preserves null, and omits only undefined. It never guesses date, time, timezone, or business conversion; applications must project values such as Date into their documented wire representation before calling it.
  • Run the consuming repo's type checks or tests after generation.