Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ Versions before 0.8.0 are in the [git tags](https://github.com/leemour/cli-core/
Every entry says what changed as a caller sees it, why, and what to watch for — the rules are
[`docs/dev/CONVENTIONS.md`](docs/dev/CONVENTIONS.md#the-changelog).

## Unreleased
## 0.17.0 — 03.10.2026

### Changed — may break callers

- Consumers switching exhaustively over `SchemaNode` or API parameter locations must handle explicit unions and RPC body parameters. Existing HTTP models generate the same artifacts.

### Added

- API generators preserve explicit unions and Boolean literals, validate nested references, and emit schema definitions for shared command input traversal. RPC parameters can belong to the JSON body; multipart references retain their format.
- API generators preserve explicit unions and Boolean literals, validate nested references, and emit schema definitions for shared command input traversal. RPC parameters can belong to the JSON body; multipart references retain their format. Source adapters can mark secret fields so consumers keep them out of generated CLI arguments.

## 0.16.0 — 02.10.2026

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@leemour/cli-core",
"version": "0.16.0",
"version": "0.17.0",
"description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
"license": "MIT",
"author": "Viacheslav Ptsarev",
Expand Down
9 changes: 7 additions & 2 deletions src/codegen/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ export interface ManifestOperation {
parameters: readonly {
name: string
in: "path" | "query" | "header" | "body"
sensitive?: boolean
required: boolean
description?: string
schema: SchemaNode
}[]
request?: { required: boolean; confidence: Confidence; schema?: string }
response?: { confidence: Confidence; schema?: string }
response?: { confidence: Confidence; schema?: string; sensitive?: boolean }
}

const withoutUndefined = <T extends object>(value: T): T =>
Expand All @@ -45,7 +46,11 @@ const toManifest = (operation: ApiOperation, tree: SchemaTree): ManifestOperatio
})
: undefined,
response: operation.response
? withoutUndefined({ confidence: operation.response.confidence, schema: tree.responseName(operation.id) })
? withoutUndefined({
confidence: operation.response.confidence,
schema: tree.responseName(operation.id),
sensitive: operation.response.schema?.sensitive,
})
: undefined,
})

Expand Down
2 changes: 2 additions & 0 deletions src/codegen/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface RpcBinding {
export type Binding = HttpBinding | RpcBinding

interface SchemaCommon {
sensitive?: boolean
description?: string
nullable?: boolean
deprecated?: boolean
Expand Down Expand Up @@ -82,6 +83,7 @@ export interface ApiSchema {
export interface ApiParameter {
name: string
in: "path" | "query" | "header" | "body"
sensitive?: boolean
required: boolean
description?: string
schema: SchemaNode
Expand Down
7 changes: 4 additions & 3 deletions src/codegen/unions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const model: ApiModel = {
source: { kind: "other" },
schemas: [
{ id: "Address", schema: { type: "union", of: [{ type: "integer", format: "int64" }, { type: "string" }] } },
{ id: "File", schema: { type: "string", format: "binary" } },
{ id: "File", schema: { type: "string", format: "binary", sensitive: true } },
{
id: "Node",
schema: {
Expand All @@ -40,7 +40,7 @@ const model: ApiModel = {
binding: { kind: "rpc", name: "readNode" },
tags: [],
parameters: [{ name: "address", in: "body", required: true, schema: { type: "ref", ref: "Address" } }],
response: { required: true, confidence: "contract", schema: { type: "ref", ref: "Node" } },
response: { required: true, confidence: "contract", schema: { type: "ref", ref: "Node", sensitive: true } },
effect: "read",
source: { location: "methods/readNode" },
},
Expand Down Expand Up @@ -103,9 +103,10 @@ describe("generated unions", () => {

it("emits runtime definitions with source formats and resolves response references", async () => {
const { definitions } = await import(join(root, "definitions.ts"))
expect(definitions.File).toEqual({ type: "string", format: "binary" })
expect(definitions.File).toEqual({ type: "string", format: "binary", sensitive: true })
const { operations } = await import(join(root, "manifest.ts"))
expect(operations[0].response.schema).toBe("Node")
expect(operations[0].response.sensitive).toBe(true)
expect(definitions.Node.type).toBe("union")
})

Expand Down
Loading