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
sumr kontract generate --source platform# one sourcesumr kontract generate --source platform --target api-nestjs# one targetsumr kontract generate --clean# preflight before cleaning selected outputsFlags 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.
--cleanRepeat the write-free configured-generator preflight, then delete selected outputs and the Kontract cache before generation.
--verboseShow detailed generation output.
--quietSuppress all output except errors.
--help, -hShow 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-audiencesmetadata can drivegenerator.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 thegenerate --cleanpreflight before selected output or cache is deleted. - On a
typescript-nestjstarget,operationContract: trueemitshttp/operations.tsand requiresdto: zod,dto: class-validator, ordto: both. Each standard JSON controller route uses exactly one generated@ContractOperation(Operation)decorator: it invokes native nestjs-zodZodResponseruntime metadata and preserves the handler return constraint. The public@sumrco/cli/eslintrule rejects redundant@ZodResponseand@ZodSerializerDtodecorators. - The NestJS ESLint rule resolves direct
http/operationsimports and generatedhttp/index.tsdirectory 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, ordto: both.zod: trueindependently emits framework-neutral Zod schemas;dto: zodordto: bothemits Zod DTO constructors. Deprecated Booleandtosand Booleandtoremain accepted: true withzod: truenormalizes toboth, true without Zod toclass-validator, false withzod: truetozod, and false without Zod tonone. Do not combine an explicit stringdtomode withdtos; configuration validation rejects it. - OpenAPI object schemas are open when
additionalPropertiesis 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. AddadditionalProperties: falseto 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 andContractParameterBagPipe(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: trueemits exactly one target-wideshared/http/foundation.tswith the onlyContractModule, canonical exception filter, and DI-preserving global providers, includingZodSerializerInterceptor. Each servicehttp/foundation.tsis a facade that re-exports that boundary and retains only service-specificbuildOpenApiConfig()andcleanupOpenApiDoc().controllers: trueadds thin controller/port/module adapters, whileerrors,mappers,tests, andbrunoadd 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
defaulterror 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
errorEnvelopeprojection, includingbodyKey, required outerstaticFields, and core status/message/type/code/details keys.sumr kontract validateruns this configured NestJS generator preflight without writes;sumr kontract generate --cleanrepeats it before deleting selected output or cache. - Required request bodies enforce a declared
Content-Typethrough the documented 415 contract. Constant or single-enum response headers become generated@Headerdecorators; dynamic values remain application-owned.CONTRACT_ERROR_OBSERVERreceives only redacted operation, provenance, category, status, and schema diagnostics—never the raw error, message, Zod input, or payload. - Structured
envelopeanderrorEnvelopesettings 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 requiresfoundation: true;errorEnveloperequireserrors: true.envelopeDataKeyis deprecated compatibility syntax forenvelope.dataKeyand cannot be combined withenvelope. - 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) orframework: fastifyselects the adapter. Every binary file requires a positivemaxLength; file arrays and repeated non-file arrays also require a positivemaxItems. - Generated Express controllers require
@nestjs/platform-express. Generated Fastify controllers use a buffered@fastify/multipartruntime and require@nestjs/platform-fastify,fastify, and@fastify/multipart; generated multipart adapters are not streaming upload APIs.dto: class-validatoranddto: bothrequireclass-transformerandclass-validator, whiletests: truerequires@nestjs/testingandsupertest. These packages belong to the consuming application or isolated consumer matrix, never Kontract's rootpackage.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 rootpackage.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. AnexternalValueexample fails deterministic generation instead of bypassing validation. - For typed JSON responses, standalone
typescript-fetchclients call a consumer-owneddecodeJson(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, generatedtoContractstructurally validates already-contract-shaped values, preservesnull, and omits onlyundefined. It never guesses date, time, timezone, or business conversion; applications must project values such asDateinto their documented wire representation before calling it. - Run the consuming repo's type checks or tests after generation.