From 6022bf2b595d403841061964bc511082fba8db62 Mon Sep 17 00:00:00 2001 From: Lagoni <68890168+ALagoni97@users.noreply.github.com> Date: Mon, 13 Jul 2026 18:57:20 +0200 Subject: [PATCH 1/2] fix(http): type context parameters and headers with concrete generated models The HTTP fetch client context interface discarded the fully-typed parameter class and headers model that are already generated, emitting a structural stub (`{ getChannelWithParameters }` / `{ marshal }`) instead. Consumers got no type support on `context.parameters` or `context.requestHeaders`. Thread the concrete `channelParameters`/`channelHeaders` types into `generateContextInterface` (mirroring the EventSource protocol) so the context references the real classes. The parameter class still exposes `getChannelWithParameters`, so URL building is unaffected; operations without a typed headers model keep the structural `{ marshal }` fallback. Co-Authored-By: Claude Opus 4.8 --- .../channels/protocols/http/client.ts | 26 ++++++++++++------- .../channels/protocols/http/index.ts | 3 ++- .../generators/typescript/channels/types.ts | 1 + .../src/request-reply/channels/http_client.ts | 8 +++--- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/codegen/generators/typescript/channels/protocols/http/client.ts b/src/codegen/generators/typescript/channels/protocols/http/client.ts index 57357485..7b83cbc5 100644 --- a/src/codegen/generators/typescript/channels/protocols/http/client.ts +++ b/src/codegen/generators/typescript/channels/protocols/http/client.ts @@ -17,6 +17,7 @@ export function renderHttpFetchClient({ replyMessageType, replyMessageModule, channelParameters, + channelHeaders, method, servers = [], subName = pascalCase(requestTopic), @@ -43,7 +44,8 @@ export function renderHttpFetchClient({ const contextInterface = generateContextInterface( contextInterfaceName, messageType, - hasParameters, + channelParameters?.type, + channelHeaders?.type, method ); @@ -92,7 +94,8 @@ ${functionCode}`; function generateContextInterface( interfaceName: string, messageType: string | undefined, - hasParameters: boolean, + parametersType: string | undefined, + headersType: string | undefined, method: string ): string { const fields: string[] = []; @@ -102,16 +105,19 @@ function generateContextInterface( fields.push(` payload: ${messageType};`); } - // Add parameters field if operation has path parameters - if (hasParameters) { - fields.push( - ` parameters: { getChannelWithParameters: (path: string) => string };` - ); + // Reference the concrete generated parameter class so consumers get typed + // query/path parameters. It still exposes getChannelWithParameters, so the + // buildUrlWithParameters call in the function body keeps working. + if (parametersType) { + fields.push(` parameters: ${parametersType};`); } - // Add requestHeaders field (optional) for operations that support typed headers - // This is always optional since headers can also be passed via additionalHeaders - fields.push(` requestHeaders?: { marshal: () => string };`); + // Reference the concrete generated headers model when available; fall back to + // the structural marshal contract otherwise. Always optional since headers can + // also be passed via additionalHeaders. + fields.push( + ` requestHeaders?: ${headersType ?? '{ marshal: () => string }'};` + ); const fieldsStr = fields.length > 0 ? `\n${fields.join('\n')}\n` : ''; diff --git a/src/codegen/generators/typescript/channels/protocols/http/index.ts b/src/codegen/generators/typescript/channels/protocols/http/index.ts index c884044f..170e244e 100644 --- a/src/codegen/generators/typescript/channels/protocols/http/index.ts +++ b/src/codegen/generators/typescript/channels/protocols/http/index.ts @@ -84,7 +84,7 @@ function generateForOperations( parameters: ConstrainedObjectModel | undefined ): HttpRenderType[] { const renders: HttpRenderType[] = []; - const {generator, payloads} = context; + const {generator, payloads, headers} = context; const functionTypeMapping = generator.functionTypeMapping?.[channel.id()]; for (const operation of channel.operations().all()) { @@ -138,6 +138,7 @@ function generateForOperations( method: httpMethod.toUpperCase(), channelParameters: parameters !== undefined ? parameters : undefined, + channelHeaders: headers, includesStatusCodes: replyIncludesStatusCodes, description, deprecated diff --git a/src/codegen/generators/typescript/channels/types.ts b/src/codegen/generators/typescript/channels/types.ts index 005a15ef..d3c329cf 100644 --- a/src/codegen/generators/typescript/channels/types.ts +++ b/src/codegen/generators/typescript/channels/types.ts @@ -284,6 +284,7 @@ export interface RenderHttpParameters { replyMessageType: string; replyMessageModule: string | undefined; channelParameters: ConstrainedObjectModel | undefined; + channelHeaders?: ConstrainedObjectModel | undefined; subName?: string; functionName?: string; method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'; diff --git a/test/runtime/typescript/src/request-reply/channels/http_client.ts b/test/runtime/typescript/src/request-reply/channels/http_client.ts index 5a3ab19f..0eaee9d3 100644 --- a/test/runtime/typescript/src/request-reply/channels/http_client.ts +++ b/test/runtime/typescript/src/request-reply/channels/http_client.ts @@ -2003,8 +2003,8 @@ async function getMultiStatusResponse(context: GetMultiStatusResponseContext = { } export interface GetGetUserItemContext extends HttpClientContext { - parameters: { getChannelWithParameters: (path: string) => string }; - requestHeaders?: { marshal: () => string }; + parameters: UserItemsParameters; + requestHeaders?: ItemRequestHeaders; } /** @@ -2127,8 +2127,8 @@ async function getGetUserItem(context: GetGetUserItemContext): Promise string }; - requestHeaders?: { marshal: () => string }; + parameters: UserItemsParameters; + requestHeaders?: ItemRequestHeaders; } /** From 60da31c047c1d86baff38301e97acd4bca8739f5 Mon Sep 17 00:00:00 2001 From: Lagoni <68890168+ALagoni97@users.noreply.github.com> Date: Mon, 13 Jul 2026 19:07:05 +0200 Subject: [PATCH 2/2] test(http): update channels snapshot for typed context parameters The OpenAPI HTTP client snapshot now reflects the concrete parameter class (`parameters: Parameter`) instead of the structural `getChannelWithParameters` stub. Co-Authored-By: Claude Opus 4.8 --- .../generators/typescript/__snapshots__/channels.spec.ts.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/codegen/generators/typescript/__snapshots__/channels.spec.ts.snap b/test/codegen/generators/typescript/__snapshots__/channels.spec.ts.snap index 92a819e5..ed56a781 100644 --- a/test/codegen/generators/typescript/__snapshots__/channels.spec.ts.snap +++ b/test/codegen/generators/typescript/__snapshots__/channels.spec.ts.snap @@ -1245,7 +1245,7 @@ async function updatePet(context: UpdatePetContext): Promise string }; + parameters: Parameter; requestHeaders?: { marshal: () => string }; }