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..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 @@ -131,3 +131,29 @@ interface ChildClient { @delete deleteStandalone(@path blobName: string): void; } + +// 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(@header("name") name?: string, @query region?: string, @query id: string): void; + + @route("/with-body") + @post + withBody(@header("name") name?: string, @query region?: string, @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, @query region?: string, @query id: string): void; + + @route("/with-body") + @post + withBody(...NameHeaderParam, @query region?: string, @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", + }, +]);