From b09fd4d199eda978d4d46976e06e97f9da5b2c35 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 19:25:54 +0000 Subject: [PATCH 1/3] Initial plan From 1819d0d67cea67e1694284f240de00b8072cf8dd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 19:51:21 +0000 Subject: [PATCH 2/3] Add ClientInitialization scenarios with optional parameters Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- ...-client-initialization-params-2025-12-1.md | 7 ++ packages/azure-http-specs/spec-summary.md | 67 +++++++++++++ .../client-initialization/client.tsp | 95 +++++++++++++++++++ .../client-initialization/main.tsp | 37 ++++++++ .../client-initialization/mockapi.ts | 80 ++++++++++++++++ 5 files changed, 286 insertions(+) create mode 100644 .chronus/changes/optional-client-initialization-params-2025-12-1.md diff --git a/.chronus/changes/optional-client-initialization-params-2025-12-1.md b/.chronus/changes/optional-client-initialization-params-2025-12-1.md new file mode 100644 index 0000000000..46ddfd1f4b --- /dev/null +++ b/.chronus/changes/optional-client-initialization-params-2025-12-1.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@azure-tools/azure-http-specs" +--- + +Add ClientInitialization scenarios with optional parameters and scenarios with both optional and required parameters diff --git a/packages/azure-http-specs/spec-summary.md b/packages/azure-http-specs/spec-summary.md index 321ab9ec26..e9c6b7b3d6 100644 --- a/packages/azure-http-specs/spec-summary.md +++ b/packages/azure-http-specs/spec-summary.md @@ -608,6 +608,73 @@ client.withQuery(id: "test-id"); // No need to pass name or region here client.withBody({ name: "test-name" }); // No need to pass name or region here ``` +### Azure_ClientGeneratorCore_ClientInitialization_OptionalAndRequiredParams + +- Endpoints: + - `get /azure/client-generator-core/client-initialization/optional-and-required-params/with-query` + - `get /azure/client-generator-core/client-initialization/optional-and-required-params/with-body` + +Client for testing a mix of optional and required parameters moved to client level. + +Parameters elevated to client level: + +- name: "test-name-value" (required header parameter) +- region: "us-west" (optional query parameter) + +Some languages may add optional parameters as properties to ClientOptions while +required parameters are constructor arguments. + +Expected client usage: + +```ts +// With all parameters provided +const client = new OptionalAndRequiredParamsClient({ + name: "test-name-value", // Required + region: "us-west" // Optional +}); + +client.withQuery(id: "test-id"); // No need to pass name or region here +client.withBody({ name: "test-name" }); // No need to pass name or region here + +// With only required parameter +const clientRequiredOnly = new OptionalAndRequiredParamsClient({ + name: "test-name-value" // Required + // region is omitted (optional) +}); +``` + +### Azure_ClientGeneratorCore_ClientInitialization_OptionalParams + +- Endpoints: + - `get /azure/client-generator-core/client-initialization/optional-params/with-query` + - `get /azure/client-generator-core/client-initialization/optional-params/with-body` + +Client for testing optional parameters moved to client level. + +Parameters elevated to client level (all optional): + +- name: "test-name-value" (optional header parameter) +- region: "us-west" (optional query parameter) + +Some languages may add optional parameters as properties to ClientOptions. + +Expected client usage: + +```ts +// With all optional parameters provided +const client = new OptionalParamsClient({ + name: "test-name-value", + region: "us-west" +}); + +client.withQuery(id: "test-id"); // No need to pass name or region here +client.withBody({ name: "test-name" }); // No need to pass name or region here + +// Without optional parameters (using defaults/omitting) +const clientNoParams = new OptionalParamsClient(); +clientNoParams.withQuery(id: "test-id"); +``` + ### Azure_ClientGeneratorCore_ClientInitialization_ParamAlias - Endpoints: diff --git a/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/client.tsp b/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/client.tsp index b2e9c79eb4..5903935854 100644 --- a/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/client.tsp +++ b/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/client.tsp @@ -47,6 +47,22 @@ model ParamAliasClientOptions { blobName: string; } +model OptionalParamsClientOptions { + @doc("Optional name parameter. This parameter is used as a header in all operations.") + name?: string; + + @doc("Optional region parameter. This parameter is used as a query parameter.") + region?: string; +} + +model OptionalAndRequiredParamsClientOptions { + @doc("Required name parameter. This parameter is used as a header in all operations.") + name: string; + + @doc("Optional region parameter. This parameter is used as a query parameter.") + region?: string; +} + // Scenario 1: Header parameter moved to client level @scenarioDoc(""" Client for testing header parameter moved to client level. @@ -244,3 +260,82 @@ namespace ParentClient { deleteStandalone is Service.ChildClient.deleteStandalone; } } + +// Scenario 7: Optional parameters moved to client level +@scenarioDoc(""" + Client for testing optional parameters moved to client level. + + Parameters elevated to client level (all optional): + - name: "test-name-value" (optional header parameter) + - region: "us-west" (optional query parameter) + + Some languages may add optional parameters as properties to ClientOptions. + + Expected client usage: + ```ts + // With all optional parameters provided + const client = new OptionalParamsClient({ + name: "test-name-value", + region: "us-west" + }); + + client.withQuery(id: "test-id"); // No need to pass name or region here + client.withBody({ name: "test-name" }); // No need to pass name or region here + + // Without optional parameters (using defaults/omitting) + const clientNoParams = new OptionalParamsClient(); + clientNoParams.withQuery(id: "test-id"); + ``` + """) +@scenario +@global.Azure.ClientGenerator.Core.client({ + name: "OptionalParamsClient", + service: Service, +}) +@global.Azure.ClientGenerator.Core.clientInitialization(OptionalParamsClientOptions) +@route("/optional-params") +interface OptionalParams { + withQuery is Service.OptionalParams.withQuery; + withBody is Service.OptionalParams.withBody; +} + +// Scenario 8: Optional and required parameters moved to client level +@scenarioDoc(""" + Client for testing a mix of optional and required parameters moved to client level. + + Parameters elevated to client level: + - name: "test-name-value" (required header parameter) + - region: "us-west" (optional query parameter) + + Some languages may add optional parameters as properties to ClientOptions while + required parameters are constructor arguments. + + Expected client usage: + ```ts + // With all parameters provided + const client = new OptionalAndRequiredParamsClient({ + name: "test-name-value", // Required + region: "us-west" // Optional + }); + + client.withQuery(id: "test-id"); // No need to pass name or region here + client.withBody({ name: "test-name" }); // No need to pass name or region here + + // With only required parameter + const clientRequiredOnly = new OptionalAndRequiredParamsClient({ + name: "test-name-value" // Required + // region is omitted (optional) + }); + ``` + """) +@scenario +@global.Azure.ClientGenerator.Core.client({ + name: "OptionalAndRequiredParamsClient", + service: Service, +}) +@global.Azure.ClientGenerator.Core.clientInitialization(OptionalAndRequiredParamsClientOptions) +@route("/optional-and-required-params") +interface OptionalAndRequiredParams { + withQuery is Service.OptionalAndRequiredParams.withQuery; + withBody is Service.OptionalAndRequiredParams.withBody; +} diff --git a/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/main.tsp b/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/main.tsp index 883e1218aa..e9450ed235 100644 --- a/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/main.tsp +++ b/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/main.tsp @@ -131,3 +131,40 @@ interface ChildClient { @delete deleteStandalone(@path blobName: string): void; } + +// Common models for optional parameters scenarios +model OptionalNameHeaderParam { + @header("name") + name?: string; +} + +model OptionalRegionQueryParam { + @query + region?: string; +} + +// Scenario 7: Optional parameters moved to client level +@doc("Operations with optional parameters that should be moved to client level") +@route("/optional-params") +interface OptionalParams { + @route("/with-query") + @get + withQuery(...OptionalNameHeaderParam, ...OptionalRegionQueryParam, @query id: string): void; + + @route("/with-body") + @post + withBody(...OptionalNameHeaderParam, ...OptionalRegionQueryParam, @body body: Input): void; +} + +// Scenario 8: Optional and required parameters mixed at client level +@doc("Operations with both optional and required parameters that should be moved to client level") +@route("/optional-and-required-params") +interface OptionalAndRequiredParams { + @route("/with-query") + @get + withQuery(...NameHeaderParam, ...OptionalRegionQueryParam, @query id: string): void; + + @route("/with-body") + @post + withBody(...NameHeaderParam, ...OptionalRegionQueryParam, @body body: Input): void; +} diff --git a/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/mockapi.ts b/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/mockapi.ts index 1d2aaf9951..1c19112cfc 100644 --- a/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/mockapi.ts +++ b/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/mockapi.ts @@ -221,3 +221,83 @@ Scenarios.Azure_ClientGeneratorCore_ClientInitialization_ParentClient_ChildClien kind: "MockApiDefinition", }, ]); + +// Mock responses for OptionalParams scenario +Scenarios.Azure_ClientGeneratorCore_ClientInitialization_OptionalParams = passOnSuccess([ + { + uri: "/azure/client-generator-core/client-initialization/optional-params/with-query", + method: "get", + request: { + query: { + id: "test-id", + region: "us-west", + }, + headers: { + name: "test-name-value", + }, + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", + }, + { + uri: "/azure/client-generator-core/client-initialization/optional-params/with-body", + method: "post", + request: { + query: { + region: "us-west", + }, + headers: { + name: "test-name-value", + }, + body: json({ + name: "test-name", + }), + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", + }, +]); + +// Mock responses for OptionalAndRequiredParams scenario +Scenarios.Azure_ClientGeneratorCore_ClientInitialization_OptionalAndRequiredParams = passOnSuccess([ + { + uri: "/azure/client-generator-core/client-initialization/optional-and-required-params/with-query", + method: "get", + request: { + query: { + id: "test-id", + region: "us-west", + }, + headers: { + name: "test-name-value", + }, + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", + }, + { + uri: "/azure/client-generator-core/client-initialization/optional-and-required-params/with-body", + method: "post", + request: { + query: { + region: "us-west", + }, + headers: { + name: "test-name-value", + }, + body: json({ + name: "test-name", + }), + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", + }, +]); From d39b99c004d5351d56029d0cee1d252c73ec2049 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 06:39:42 +0000 Subject: [PATCH 3/3] Remove unnecessary models and inline optional parameters Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com> --- .../client-initialization/main.tsp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/main.tsp b/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/main.tsp index e9450ed235..6789b87b70 100644 --- a/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/main.tsp +++ b/packages/azure-http-specs/specs/azure/client-generator-core/client-initialization/main.tsp @@ -132,28 +132,17 @@ interface ChildClient { deleteStandalone(@path blobName: string): void; } -// Common models for optional parameters scenarios -model OptionalNameHeaderParam { - @header("name") - name?: string; -} - -model OptionalRegionQueryParam { - @query - region?: string; -} - // Scenario 7: Optional parameters moved to client level @doc("Operations with optional parameters that should be moved to client level") @route("/optional-params") interface OptionalParams { @route("/with-query") @get - withQuery(...OptionalNameHeaderParam, ...OptionalRegionQueryParam, @query id: string): void; + withQuery(@header("name") name?: string, @query region?: string, @query id: string): void; @route("/with-body") @post - withBody(...OptionalNameHeaderParam, ...OptionalRegionQueryParam, @body body: Input): void; + withBody(@header("name") name?: string, @query region?: string, @body body: Input): void; } // Scenario 8: Optional and required parameters mixed at client level @@ -162,9 +151,9 @@ interface OptionalParams { interface OptionalAndRequiredParams { @route("/with-query") @get - withQuery(...NameHeaderParam, ...OptionalRegionQueryParam, @query id: string): void; + withQuery(...NameHeaderParam, @query region?: string, @query id: string): void; @route("/with-body") @post - withBody(...NameHeaderParam, ...OptionalRegionQueryParam, @body body: Input): void; + withBody(...NameHeaderParam, @query region?: string, @body body: Input): void; }