Skip to content

Commit 195eda1

Browse files
maxholmanclaude
andcommitted
feat: make constructor input optional when all params are optional
Commands with only optional query/header params no longer require an empty {} argument. The input parameter gets hasQuestionToken and the destructuring uses ?? {} fallback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 20720b9 commit 195eda1

6 files changed

Lines changed: 33 additions & 10 deletions

File tree

__tests__/fixtures/petstore/commands.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* WARN: Do not edit directly.
55
*
6-
* Generated on 2026-03-17T13:15:35.006Z
6+
* Generated on 2026-04-23T13:57:47.210Z
77
*
88
*/
99
/** eslint-disable max-classes */
@@ -18,7 +18,8 @@ import type {
1818
} from "./types.js";
1919

2020
/**
21-
* Tagged template literal that applies encodeURIComponent to all interpolated values, protecting path integrity from characters like `/` and `#`.
21+
* Tagged template literal that applies encodeURIComponent to all interpolated
22+
* values, protecting path integrity from characters like `/` and `#`.
2223
* @example encodePath`/users/${userId}` // "/users/foo%2Fbar"
2324
*/
2425
function encodePath(
@@ -61,8 +62,8 @@ export class FindPetsCommand extends Command<
6162
> {
6263
public override method = "get" as const;
6364

64-
constructor(input: FindPetsCommandInput) {
65-
const { tags, limit } = input;
65+
constructor(input?: FindPetsCommandInput) {
66+
const { tags, limit } = input ?? {};
6667
super("/pets", undefined, stripUndefined({ tags, limit }));
6768
}
6869
}

__tests__/fixtures/petstore/hono-valibot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* WARN: Do not edit directly.
55
*
6-
* Generated on 2026-03-17T13:15:35.006Z
6+
* Generated on 2026-04-23T13:57:47.210Z
77
*
88
*/
99

__tests__/fixtures/petstore/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* WARN: Do not edit directly.
55
*
6-
* Generated on 2026-03-17T13:15:35.006Z
6+
* Generated on 2026-04-23T13:57:47.210Z
77
*
88
*/
99
import {

__tests__/fixtures/petstore/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* WARN: Do not edit directly.
55
*
6-
* Generated on 2026-03-17T13:15:35.006Z
6+
* Generated on 2026-04-23T13:57:47.210Z
77
*
88
*/
99

__tests__/fixtures/petstore/valibot.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* WARN: Do not edit directly.
55
*
6-
* Generated on 2026-03-17T13:15:35.006Z
6+
* Generated on 2026-04-23T13:57:47.210Z
77
*
88
*/
99
import * as v from "valibot";
@@ -24,7 +24,15 @@ export const petSchema = v.intersect([
2424
]);
2525
export const findPetsCommandQuerySchema = v.strictObject({
2626
tags: v.exactOptional(v.array(v.string())),
27-
limit: v.exactOptional(v.pipe(v.number(), v.integer())),
27+
limit: v.exactOptional(
28+
v.pipe(
29+
v.string(),
30+
v.digits(),
31+
v.transform((n) => Number.parseInt(n, 10)),
32+
v.number(),
33+
v.integer(),
34+
),
35+
),
2836
});
2937
export const addPetCommandBodySchema = newPetSchema;
3038
export const findPetByIdCommandParamsSchema = v.strictObject({

lib/process-document.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,16 @@ export async function processOpenApiDocument(
971971

972972
const hasHeaders = !!headerType && headerParameters.length > 0;
973973

974+
const allInputOptional =
975+
!hasParams &&
976+
!hasJsonBody &&
977+
!hasNonJsonBody &&
978+
queryParameters.every((qp) => !qp.required);
979+
980+
const allHeadersOptional = headerParameters.every(
981+
(hp) => !hp.required,
982+
);
983+
974984
if (hasNonJsonBody || hasJsonBody || hasQuery || hasParams || hasHeaders) {
975985
const ctor = commandClassDeclaration.addConstructor();
976986

@@ -991,12 +1001,14 @@ export async function processOpenApiDocument(
9911001
const cctorParam = ctor.addParameter({
9921002
name: "input",
9931003
type: inputType.getName(),
1004+
...(allInputOptional && { hasQuestionToken: true }),
9941005
});
9951006

9961007
if (hasHeaders) {
9971008
ctor.addParameter({
9981009
name: "headers",
9991010
type: headerType.getName(),
1011+
...(allHeadersOptional && { hasQuestionToken: true }),
10001012
});
10011013
}
10021014

@@ -1007,7 +1019,9 @@ export async function processOpenApiDocument(
10071019
declarations: [
10081020
{
10091021
kind: StructureKind.VariableDeclaration,
1010-
initializer: cctorParam.getName(),
1022+
initializer: allInputOptional
1023+
? `${cctorParam.getName()} ?? {}`
1024+
: cctorParam.getName(),
10111025
name: iife(() => {
10121026
switch (true) {
10131027
case paramsToDestructure.length > 0 && hasNonJsonBody:

0 commit comments

Comments
 (0)