Clients
This page documents the client behavior as well as how to customize clients.
Default Behavior
Section titled “Default Behavior”Basic Rules
Section titled “Basic Rules”By default, each namespace with the @service decorator is generated as a separate root client. The client name is the namespace name with Client appended as a suffix.
Sub-namespaces and interfaces under each root client are generated as sub clients with a hierarchical structure. The sequence of sub clients is determined by the order of namespace declarations, followed by interface declarations.
The root client’s SDK namespace corresponds to the namespace decorated with @service. If a sub client originates from a sub-namespace, its SDK namespace corresponds to that sub-namespace. If it originates from an interface, its SDK namespace corresponds to the namespace containing the interface.
By default, sub clients can only be initialized by the root client or their parent sub client.
Different languages organize clients and sub clients differently. Refer to the examples below for details.
Single Client
Section titled “Single Client”@versioned(Versions)@service(#{ title: "Pet Store" })namespace PetStore;
enum Versions { v1,}
@route("/feed") op feed(): void;
@route("/pet") op pet(): void;# generated _client.pyclass PetStoreClient(_PetStoreClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated _operations/_operations.pyclass _PetStoreClientOperationsMixin:
@distributed_trace def feed(self, **kwargs: Any) -> None:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store import PetStoreClient
client = PetStoreClient()client.feed()client.pet()namespace PetStore{ public partial class PetStoreClient { public PetStoreClient(Uri endpoint, PetStoreClientOptions options){}
public virtual async Task<Response> FeedAsync(RequestContext context = null) {} public virtual Response Feed(RequestContext context = null) {} public virtual async Task<Response> PetAsync(RequestContext context = null) {} public virtual Response Pet(RequestContext context = null) {} }}
// Create the client and invoke the operationsusing PetStore;
PetStoreClient client = new PetStoreClient(url, options);client.Feed();client.Pet();import { PetStoreClient } from "@azure/package-name";
const client = new PetStoreClient();client.feed();client.pet();// Client builder classpackage petstore;
@ServiceClientBuilder(serviceClients = { PetStoreClient.class, PetStoreAsyncClient.class })public final class PetStoreClientBuilder implements HttpTrait<PetStoreClientBuilder>, ConfigurationTrait<PetStoreClientBuilder>, EndpointTrait<PetStoreClientBuilder> {
public PetStoreClientBuilder();
public PetStoreClient buildClient();}
// Client class@ServiceClient(builder = PetStoreClientBuilder.class)public final class PetStoreClient { public void feed(); public void pet();}
// UsagePetStoreClient client = new PetStoreClientBuilder().buildClient();client.feed();client.pet();// generated petstore_client.gotype PetStoreClient struct {}
func NewPetStoreClient() *PetStoreClient { return &PetStoreClient{}}
func (client *PetStoreClient) Feed(ctx context.Context, options *PetStoreClientFeedOptions) (PetStoreClientFeedResponse, error) {}
func (client *PetStoreClient) Pet(ctx context.Context, options *PetStoreClientPetOptions) (PetStoreClientPetResponse, error) {}
// generated options.gotype PetStoreClientFeedOptions struct {}type PetStoreClientPetOptions struct {}
// generated response.gotype PetStoreClientFeedResponse struct {}type PetStoreClientPetResponse struct {}
// Usage SamplepetStoreClient := NewPetStoreClient()petStoreClient.Feed(context.Background(), &PetStoreClientFeedOptions{})petStoreClient.Pet(context.Background(), &PetStoreClientPetOptions{})Client with One-Layer Child Sub Clients
Section titled “Client with One-Layer Child Sub Clients”The PetStore includes two sub clients: Dogs, which belongs to a subnamespace, and Cats, which is part of an interface.
@versioned(Versions)@service(#{ title: "Pet Store", version: "v1" })namespace PetStore;
enum Versions { v1,}
@route("/dogs")interface Dogs { @route("feed") feed(): void; @route("pet") pet(): void;}
@route("/cats")namespace Cats { @route("feed") op feed(): void; @route("pet") op pet(): void;}# generated _client.pyclass PetStoreClient: def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated operations/_operations.pyclass DogsOperations:
@distributed_trace def feed(self, **kwargs: Any) -> None:
@distributed_trace def pet(self, **kwargs: Any) -> None:
# generated cats/operations/_operations.pyclass CatsOperations:
@distributed_trace def feed(self, **kwargs: Any) -> None:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store import PetStoreClient
client = PetStoreClient()client.dogs.feed()client.dogs.pet()client.cats.feed()client.cats.pet()using PetStore;
PetStoreClient client = new PetStoreClient();client.GetDogsClient().Feed();client.GetDogsClient().Pet();client.GetCatsClient().Feed();client.GetCatsClient().Pet();import { PetStoreClient } from "@azure/package-name";
const client = new PetStoreClient();client.dogs.feed();client.dogs.pet();client.cats.feed();client.cats.pet();// Client builder classpackage petstore;
@ServiceClientBuilder( serviceClients = { CatsClient.class, DogsClient.class, CatsAsyncClient.class, DogsAsyncClient.class })public final class PetStoreClientBuilder implements HttpTrait<PetStoreClientBuilder>, ConfigurationTrait<PetStoreClientBuilder>, EndpointTrait<PetStoreClientBuilder> {
public PetStoreClientBuilder();
public CatsClient buildCatsClient(); public DogsClient buildDogsClient();}
// Client class@ServiceClient(builder = PetStoreClientBuilder.class)public final class DogsClient { public void feed(); public void pet();}
@ServiceClient(builder = PetStoreClientBuilder.class)public final class CatsClient { public void feed(); public void pet();}
// UsagePetStoreClientBuilder builder = new PetStoreClientBuilder();
DogsClient dogsClient = builder.buildDogsClient();dogsClient.feed();dogsClient.pet();
CatsClient catsClient = builder.buildCatsClient();catsClient.feed();catsClient.pet();// generated petstore_client.gotype PetStoreClient struct {}
func (client *PetStoreClient) NewPetStoreCatsClient() *PetStoreCatsClient { return &PetStoreCatsClient{}}
func (client *PetStoreClient) NewPetStoreDogsClient() *PetStoreDogsClient { return &PetStoreDogsClient{}}
// generated petstoredogs_client.gotype PetStoreDogsClient struct {}
func (client *PetStoreDogsClient) Feed(ctx context.Context, options *PetStoreDogsClientFeedOptions) (PetStoreDogsClientFeedResponse, error) {}
func (client *PetStoreDogsClient) Pet(ctx context.Context, options *PetStoreDogsClientPetOptions) (PetStoreDogsClientPetResponse, error) {}
// generated petstorecats_client.gotype PetStoreCatsClient struct {}
func (client *PetStoreCatsClient) Feed(ctx context.Context, options *PetStoreCatsClientFeedOptions) (PetStoreCatsClientFeedResponse, error) {}
func (client *PetStoreCatsClient) Pet(ctx context.Context, options *PetStoreCatsClientPetOptions) (PetStoreCatsClientPetResponse, error) {}
// generated options.gotype PetStoreDogsClientFeedOptions struct {}type PetStoreDogsClientPetOptions struct {}type PetStoreCatsClientFeedOptions struct {}type PetStoreCatsClientPetOptions struct {}
// generated response.gotype PetStoreDogsClientFeedResponse {}type PetStoreDogsClientPetResponse {}type PetStoreCatsClientFeedResponse {}type PetStoreCatsClientPetResponse {}
// Usage SamplepetStoreClient := NewPetStoreClient()petStoreCatsClient := petStoreClient.NewPetStoreCatsClient()petStoreCatsClient.Feed(context.Background(), &PetStoreCatsClientFeedOptions{})petStoreCatsClient.Pet(context.Background(), &PetStoreCatsClientPetOptions{})petStoreDogsClient := petStoreClient.NewPetStoreDogsClient()petStoreDogsClient.Feed(context.Background(), &PetStoreDogsClientFeedOptions{})petStoreDogsClient.Pet(context.Background(), &PetStoreDogsClientPetOptions{})Client with Multi-Layer Child Sub Clients
Section titled “Client with Multi-Layer Child Sub Clients”PetStore has three sub clients: Billings (from an interface), Pets (from a sub-namespace), and Actions (from an interface). Pets also contains a nested sub client, Actions, from an interface.
@service(#{ title: "Pet Store", version: "v1" })namespace PetStore;
@route("/info") op info(): void;
@route("/billings")interface Billings { @route("history") history(): void;}
@route("/pets")namespace Pets { @route("info") op info(): void;
@route("/actions") interface Actions { @route("feed") feed(): void; @route("pet") pet(): void; }}
@route("/actions")interface Actions { @route("open") open(): void; @route("close") close(): void;}# generated _client.pyclass PetStoreClient(_PetStoreClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated operations/_operations.pyclass _PetStoreClientOperationsMixin:
@distributed_trace def info(self, **kwargs: Any) -> None:
class BillingsOperations:
@distributed_trace def history(self, **kwargs: Any) -> None:
class ActionsOperations:
@distributed_trace def open(self, **kwargs: Any) -> None:
@distributed_trace def close(self, **kwargs: Any) -> None:
# generated pets/operations/_operations.pyclass PetsOperations:
@distributed_trace def info(self, **kwargs: Any) -> None:
class PetsActionsOperations:
@distributed_trace def feed(self, **kwargs: Any) -> None:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store import PetStoreClient
client = PetStoreClient()client.info()client.billings.history()client.pets.info()client.pets.actions.feed()client.pets.actions.pet()client.actions.open()client.actions.close()using PetStore;
PetStoreClient client = new PetStoreClient();client.Info();client.GetBillingsClient().History();client.GetPetsClient().Info();client.GetPetsClient().GetPetsActionsClient().Feed();client.GetPetsClient().GetPetsActionsClient().Pet();client.GetActionsClient().Open();client.GetActionsClient().Close();import { PetStoreClient } from "@azure/package-name";
const client = new PetStoreClient();client.info();client.billings.history();client.pets.info();client.pets.actions.feed();client.pets.actions.pet();client.actions.open();client.actions.close();// Client builder classpackage petstore;
@ServiceClientBuilder( serviceClients = { PetStoreClient.class, PetsClient.class, PetsActionsClient.class, BillingsClient.class, ActionsClient.class, PetStoreAsyncClient.class, PetsAsyncClient.class, PetsActionsAsyncClient.class, BillingsAsyncClient.class, ActionsAsyncClient.class })public final class PetStoreClientBuilder implements HttpTrait<PetStoreClientBuilder>, ConfigurationTrait<PetStoreClientBuilder>, EndpointTrait<PetStoreClientBuilder> {
public PetStoreClientBuilder();
public PetStoreClient buildClient(); public PetsActionsClient buildPetsActionsClient(); public PetsClient buildPetsClient(); public BillingsClient buildBillingsClient(); public ActionsClient buildActionsClient();}
// Client class@ServiceClient(builder = PetStoreClientBuilder.class)public final class PetStoreClient { public void info();}
@ServiceClient(builder = PetStoreClientBuilder.class)public final class BillingsClient { public void history();}
@ServiceClient(builder = PetStoreClientBuilder.class)public final class PetsClient { public void info();}
@ServiceClient(builder = PetStoreClientBuilder.class)public final class PetsActionsClient { public void feed(); public void pet();}
@ServiceClient(builder = PetStoreClientBuilder.class)public final class ActionsClient { public void open(); public void close();}
// UsagePetStoreClientBuilder builder = new PetStoreClientBuilder();
PetStoreClient petStoreClient = builder.buildClient();petStoreClient.info();
BillingsClient billingsClient = builder.buildBillingsClient();billingsClient.history();
PetsClient petsClient = builder.buildPetsClient();petsClient.info();
PetsActionsClient petsActionsClient = builder.buildPetsActionsClient();petsActionsClient.feed();petsActionsClient.pet();
ActionsClient actionsClient = builder.buildActionsClient();actionsClient.open();actionsClient.close();// generated petstore_client.gotype PetStoreClient struct {}
func NewPetStoreClient() *PetStoreClient { return &PetStoreClient{}}
func (client *PetStoreClient) Info(ctx context.Context, options *PetStoreClientInfoOptions) (PetStoreClientInfoResponse, error) {}
// generated petstoreactions_client.gotype PetStoreActionsClient struct {}
func NewPetStoreActionsClient() *PetStoreActionsClient { return &PetStoreActionsClient{}}
func (client *PetStoreActionsClient) Close(ctx context.Context, options *PetStoreActionsClientCloseOptions) (PetStoreActionsClientCloseResponse, error) {}
func (client *PetStoreActionsClient) Open(ctx context.Context, options *PetStoreActionsClientOpenOptions) (PetStoreActionsClientOpenResponse, error) {}
// generated petstorebillings_client.gotype PetStoreBillingsClient struct {}
func NewPetStoreBillingsClient() *PetStoreBillingsClient { return &PetStoreBillingsClient{}}
func (client *PetStoreBillingsClient) History(ctx context.Context, options *PetStoreBillingsClientHistoryOptions) (PetStoreBillingsClientHistoryResponse, error) {}
// generated petstorepets_client.gotype PetStorePetsClient struct {}
func NewPetStorePetsClient() *PetStorePetsClient { return &PetStorePetsClient{}}
func (client *PetStorePetsClient) Info(ctx context.Context, options *PetStorePetsClientInfoOptions) (PetStorePetsClientInfoResponse, error) {}
// generated petstorepetsactions_client.gotype PetStorePetsActionsClient struct {}
func NewPetStorePetsActionsClient() *PetStorePetsActionsClient { return &PetStorePetsActionsClient{}}
func (client *PetStorePetsActionsClient) Feed(ctx context.Context, options *PetStorePetsActionsClientFeedOptions) (PetStorePetsActionsClientFeedResponse, error) {}
func (client *PetStorePetsActionsClient) Pet(ctx context.Context, options *PetStorePetsActionsClientPetOptions) (PetStorePetsActionsClientPetResponse, error) {}
// generated options.gotype PetStoreActionsClientCloseOptions struct {}type PetStoreActionsClientOpenOptions struct {}type PetStoreBillingsClientHistoryOptions struct {}type PetStoreClientInfoOptions struct {}type PetStorePetsActionsClientFeedOptions struct {}type PetStorePetsActionsClientPetOptions struct {}type PetStorePetsClientInfoOptions struct {}
// generated response.gotype PetStoreActionsClientCloseResponse struct {}type PetStoreActionsClientOpenResponse struct {}type PetStoreBillingsClientHistoryResponse struct {}type PetStoreClientInfoResponse struct {}type PetStorePetsActionsClientFeedResponse struct {}type PetStorePetsActionsClientPetResponse struct {}type PetStorePetsClientInfoResponse struct {}
// Usage SamplepetStoreClient := NewPetStoreClient()petStoreClient.Info(context.Background(), &PetStoreClientInfoOptions{})petStoreActionsClient := NewPetStoreActionsClient()petStoreActionsClient.Close(context.Background(), &PetStoreActionsClientCloseOptions{})petStoreActionsClient.Open(context.Background(), &PetStoreActionsClientOpenOptions{})petStoreBillingsClient := NewPetStoreBillingsClient()petStoreBillingsClient.History(context.Background(), &PetStoreBillingsClientHistoryOptions{})petStorePetsClient := NewPetStorePetsClient()petStorePetsClient.Info(context.Background(), &PetStorePetsClientInfoOptions{})petStorePetsActionsClient := NewPetStorePetsActionsClient()petStorePetsActionsClient.Feed(context.Background(), &PetStorePetsActionsClientFeedOptions{})petStorePetsActionsClient.Pet(context.Background(), &PetStorePetsActionsClientPetOptions{})Customizations
Section titled “Customizations”Customizations SHOULD always be made in a file named client.tsp alongside main.tsp.
There are two ways to customize the client hierarchy: using @clientLocation to change the location of the operations, or use @client to restructure the client hierarchy.
Be careful when you use both of them since @clientLocation could not move the client that is no longer exist with @client customization.
The @clientLocaton decorator allows you to change the location of the operations in the client hierarchy.
It can be used to move operations to an existed sub client defined by Interface or Namespace, or move the the root client of namespace with @service decorator.
This decorator is useful when you want to keep the default client hierarchy but need to change the location of some operations.
The @client decorator allows you to totally restructure the client hierarchy.
However, if any customizations are made, the client hierarchy will only reflect those customizations. The default behavior logic will no longer apply.
If customizations are made, the client’s SDK namespace will follow the namespace decorated with @client or the namespace containing the interface decorated with @client.
You can override this using @clientNamespace if needed.
The sequence of clients and sub clients is determined by the order of the @client decorators.
Move All Operations to Root Client
Section titled “Move All Operations to Root Client”This can be achieved with the augment decorator: @clientLocation from typespec-client-generator-core.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;using PetStore;
@@clientLocation(Feeds.feed, PetStore);@@clientLocation(Pets.pet, PetStore);# generated _client.pyclass PetStoreClient(_PetStoreClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated _operations/_operations.pyclass _PetStoreClientOperationsMixin:
@distributed_trace def feed(self, **kwargs: Any) -> None:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store import PetStoreClient
client = PetStoreClient()client.feed()client.pet()using PetStore;
PetStoreClient client = new PetStoreClient();client.Feed();client.Pet();import { PetStoreClient } from "@azure/package-name";
const client = new PetStoreClient();client.feed();client.pet();// Client builder classpackage petstore;
@ServiceClientBuilder(serviceClients = { PetStoreClient.class, PetStoreAsyncClient.class })public final class PetStoreClientBuilder implements HttpTrait<PetStoreClientBuilder>, ConfigurationTrait<PetStoreClientBuilder>, EndpointTrait<PetStoreClientBuilder> {
public PetStoreClientBuilder();
public PetStoreClient buildClient();}
// Client class@ServiceClient(builder = PetStoreClientBuilder.class)public final class PetStoreClient { public void feed(); public void pet();}
// UsagePetStoreClient client = new PetStoreClientBuilder().buildClient();client.feed();client.pet();// generated petstore_client.gotype PetStoreClient struct {}
func NewPetStoreClient() *PetStoreClient{ return &PetStoreClient{}}
func (client *PetStoreClient) Feed(ctx context.Context, options *PetStoreClientFeedOptions) (PetStoreClientFeedResponse, error) {}
func (client *PetStoreClient) Pet(ctx context.Context, options *PetStoreClientPetOptions) (PetStoreClientPetResponse, error) {}
// generated options.gotype PetStoreClientFeedOptions struct {}type PetStoreClientPetOptions struct {}
// generated response.gotype PetStoreClientFeedResponse struct {}type PetStoreClientPetResponse struct {}
// Usage SamplepetStoreClient := NewPetStoreClient()petStoreClient.Feed(context.Background(), &PetStoreClientFeedOptions{})petStoreClient.Pet(context.Background(), &PetStoreClientPetOptions{})Renaming the Client Name
Section titled “Renaming the Client Name”This can be achieved with the augment decorator: @clientName from typespec-client-generator-core.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
@@clientName(PetStore, "PetStoreGreatClient");# generated _client.pyclass PetStoreGreatClient(_PetStoreGreatClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated _operations/_operations.pyclass _PetStoreGreatClientOperationsMixin:
@distributed_trace def feed(self, **kwargs: Any) -> None:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store import PetStoreGreatClient
client = PetStoreGreatClient()client.feed()client.pet()using PetStore;
PetStoreGreatClient client = new PetStoreGreatClient();client.Feed();client.Pet();import { PetStoreGreatClient } from "@azure/package-name";
const client = new PetStoreGreatClient();client.feed();client.pet();// Client builder classpackage petstore;
@ServiceClientBuilder(serviceClients = { PetStoreGreatClient.class, PetStoreGreatAsyncClient.class })public final class PetStoreGreatClientBuilder implements HttpTrait<PetStoreGreatClientBuilder>, ConfigurationTrait<PetStoreGreatClientBuilder>, EndpointTrait<PetStoreGreatClientBuilder> {
public PetStoreGreatClientBuilder();
public PetStoreGreatClient buildClient();}
// Client class@ServiceClient(builder = PetStoreGreatClientBuilder.class)public final class PetStoreGreatClient { public void feed(); public void pet();}
// UsagePetStoreGreatClient client = new PetStoreGreatClientBuilder().buildClient();client.feed();client.pet();type PetStoreGreatClient struct {}
func NewPetStoreGreatClient() *PetStoreGreatClient{ return &PetStoreGreatClient{}}
func (client *PetStoreGreatClient) Feed(ctx context.Context, options *PetStoreGreatClientFeedOptions) (PetStoreGreatClientFeedResponse, error) {}
func (client *PetStoreGreatClient) Pet(ctx context.Context, options *PetStoreGreatClientPetOptions) (PetStoreGreatClientPetResponse, error) {}
// options.gotype PetStoreGreatClientFeedOptions struct {}type PetStoreGreatClientPetOptions struct {}
// response.gotype PetStoreGreatClientFeedResponse struct {}type PetStoreGreatClientPetResponse struct {}
// Usage Sampleclient := NewPetStoreGreatClient()client.Feed(context.Background(), &PetStoreGreatClientFeedOptions{})client.Pet(context.Background(), &PetStoreGreatClientPetOptions{})Renaming the Client Namespace
Section titled “Renaming the Client Namespace”This can be achieved with the augment decorator: @clientNamespace from typespec-client-generator-core.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
@@clientNamespace(PetStore, "PetStoreRenamed");# generated _client.pyclass PetStoreClient(_PetStoreClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated _operations/_operations.pyclass _PetStoreClientOperationsMixin:
@distributed_trace def feed(self, **kwargs: Any) -> None:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store_renamed import PetStoreClient
client = PetStoreClient()client.feed()client.pet()using PetStoreRenamed;
PetStoreClient client = new PetStoreClient();client.Feed();client.Pet();import { PetStoreClient } from "@azure/package-name";
const client = new PetStoreClient();client.feed();client.pet();// Client builder classpackage petstorerenamed;
@ServiceClientBuilder(serviceClients = { PetStoreClient.class, PetStoreAsyncClient.class })public final class PetStoreClientBuilder implements HttpTrait<PetStoreClientBuilder>, ConfigurationTrait<PetStoreClientBuilder>, EndpointTrait<PetStoreClientBuilder> {
public PetStoreClientBuilder();
public PetStoreClient buildClient();}
// Client class@ServiceClient(builder = PetStoreClientBuilder.class)public final class PetStoreClient { public void feed(); public void pet();}
// Usagepackage petstorerenamed;
PetStoreClient client = new PetStoreClientBuilder().buildClient();client.feed();client.pet();// NOT_SUPPORTEDSplitting the Operations into Two Clients
Section titled “Splitting the Operations into Two Clients”Two clients that separate the operations can be declared using the @client decorator from typespec-client-generator-core.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
namespace PetStoreRenamed; // this namespace will be the namespace of the clients and sub clients defined in this customization file
@client({ name: "FoodClient", service: PetStore,})interface Client1 { feed is PetStore.feed;}
@client({ name: "PetActionClient", service: PetStore,})interface Client2 { pet is PetStore.pet;}# generated _client.pyclass FoodClient(_FoodClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
class PetActionClient(_PetActionClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated _operations/_operations.pyclass _FoodClientOperationsMixin:
@distributed_trace def feed(self, **kwargs: Any) -> None:
class _PetActionClientOperationsMixin
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store_renamed import FoodClient, PetActionClient
client1 = FoodClient()client2 = PetActionClient()
client1.feed()client2.pet()using PetStoreRenamed;
PetActionClient petActionClient = new PetActionClient();FoodClient foodClient = new FoodClient();
petActionClient.Pet();foodClient.Feed();import { FoodClient, PetActionClient } from "@azure/package-name";
const client1 = new PetActionClient();const client2 = new FoodClient();client1.pet();client2.feed();// Client builder classpackage petstorerenamed;
@ServiceClientBuilder(serviceClients = { FoodClient.class, FoodAsyncClient.class })public final class FoodClientBuilder implements HttpTrait<FoodClientBuilder>, ConfigurationTrait<FoodClientBuilder>, EndpointTrait<FoodClientBuilder> {
public FoodClientBuilder();
public FoodClient buildClient();}
@ServiceClientBuilder(serviceClients = { PetActionClient.class, PetActionAsyncClient.class })public final class PetActionClientBuilder implements HttpTrait<PetActionClientBuilder>, ConfigurationTrait<PetActionClientBuilder>, EndpointTrait<PetActionClientBuilder> {
public PetActionClientBuilder();
public PetActionClient buildClient();}
// Client class@ServiceClient(builder = FoodClientBuilder.class)public final class FoodClient { public void feed();}
@ServiceClient(builder = PetActionClientBuilder.class)public final class PetActionClient { public void pet();}
// Usagepackage petstorerenamed;
FoodClient foodClient = new FoodClientBuilder().buildClient();PetActionClient petActionClient = new PetActionClientBuilder().buildClient();
foodClient.feed()petActionClient.pet()// generated food_client.gotype FoodClient struct {}
func NewFoodClient() *FoodClient{ return &FoodClient{}}
func (client *FoodClient) Feed(ctx context.Context, options *FoodClientFeedOptions) (FoodClientFeedResponse, error) {}
// generated petaction_client.gotype PetActionClient struct {}
func NewPetActionClient() *PetActionClient{ return &PetActionClient{}}
func (client *PetActionClient) Pet(ctx context.Context, options *PetActionClientPetOptions) (PetActionClientPetResponse, error) {}
// generated options.gotype FoodClientFeedOptions struct {}type PetActionClientPetOptions struct {}
// generated response.gotype FoodClientFeedResponse struct {}type PetActionClientPetResponse struct {}
// Usage SamplefoodClient := NewFoodClient()foodClient.Feed(context.Background(), &FoodClientFeedOptions{})petActionClient := NewPetActionClient()petActionClient.Pet(context.Background(), &PetActionClientPetOptions{})One Client and Two Sub Clients
Section titled “One Client and Two Sub Clients”Two sub clients that separate the operations can be declared using the @client decorator (or the @operationGroup decorator, which is an alias) from typespec-client-generator-core:
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
@client({ name: "PetStoreClient", service: PetStore,})namespace PetStoreRenamed; // this namespace will be the namespace of the clients and sub clients defined in this customization file
@operationGroupinterface OpGrp1 { feed is PetStore.feed;}
@operationGroupinterface OpGrp2 { pet is PetStore.pet;}# generated _client.pyclass PetStoreClient: def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated operations/_operations.pyclass OpGrp1Operations:
@distributed_trace def feed(self, **kwargs: Any) -> None:
class OpGrp2Operations:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store_renamed import PetStoreClient
client = PetStoreClient()
client.op_grp_1.feed()client.op_grp_2.pet()using PetStoreRenamed;
PetStoreClient client = new PetStoreClient();
client.GetOpGrp1Client().Feed();client.GetOpGrp2Client().Pet();import { PetStoreClient } from "@azure/package-name";
const client = new PetStoreClient();client.opGrp1.feed();client.opGrp2.pet();// Client builder classpackage petstorerenamed;
@ServiceClientBuilder( serviceClients = { OpGrp1Client.class, OpGrp2Client.class, OpGrp1AsyncClient.class, OpGrp2AsyncClient.class })public final class PetStoreClientBuilder implements HttpTrait<PetStoreClientBuilder>, ConfigurationTrait<PetStoreClientBuilder>, EndpointTrait<PetStoreClientBuilder> {
public OpGrp1Client buildOpGrp1Client();
public OpGrp2Client buildOpGrp2Client();}
// Client class@ServiceClient(builder = PetStoreClientBuilder.class)public final class OpGrp1Client { public void feed();}
@ServiceClient(builder = PetStoreClientBuilder.class)public final class OpGrp2Client { public void pet();}
// Usagepackage petstorerenamed;
PetStoreClientBuilder builder = new PetStoreClientBuilder();
OpGrp1Client opGrp1Client = builder.buildOpGrp1Client();opGrp1Client.feed();
OpGrp2Client opGrp2Client = builder.buildOpGrp2Client();opGrp2Client.pet();// generated petstore_client.gotype PetStoreClient struct {}
func NewPetStoreClient() *PetStoreClient{ return &PetStoreClient{}}
func (client *PetStoreClient)NewOpGrp1Client() *OpGrp1Client{ return &OpGrp1Client{}}
func (client *PetStoreClient)NewOpGrp2Client() *OpGrp2Client{ return &OpGrp2Client{}}
// generated petstoreopgrp1_client.gotype OpGrp1Client struct {}
func (client *PetStoreOpGrp1Client) Feed(ctx context.Context, options *PetStoreOpGrp1ClientFeedOptions) (PetStoreOpGrp1ClientFeedResponse, error) {}
// generated petstoreopgrp2_client.gotype OpGrp2Client struct {}
func (client *PetStoreOpGrp2Client) Pet(ctx context.Context, options *PetStoreOpGrp2ClientPetOptions) (PetStoreOpGrp2ClientPetResponse, error) {}
// generated options.gotype PetStoreOpGrp1ClientFeedOptions struct {}type PetStoreOpGrp2ClientPetOptions struct {}
// generated response.gotype PetStoreOpGrp1ClientFeedResponse struct {}type PetStoreOpGrp2ClientPetResponse struct {}
// Usage SamplepetStoreClient := NewPetStoreClient()opGrp1Client := petStoreClient.NewOpGrp1Client()opGrp1Client.Feed(context.Background(), &PetStoreOpGrp1ClientFeedOptions{})opGrp2Client := petStoreClient.NewOpGrp2Client()opGrp2Client.Pet(context.Background(),&PetStoreOpGrp2ClientPetOptions{})Splitting the Operations into Sub-Namespaces
Section titled “Splitting the Operations into Sub-Namespaces”import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
namespace NewPetStore;
@client({ name: "FoodClient", service: PetStore,})namespace Food { op feed is PetStore.feed;}
@client({ name: "PetActionClient", service: PetStore,})namespace PetAction { op pet is PetStore.pet;}# generated food/_client.pyclass FoodClient(_FoodClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated food/_operations/_operations.pyclass _FoodClientOperationsMixin:
@distributed_trace def feed(self, **kwargs: Any) -> None:
# generated petaction/_client.pyclass PetActionClient(_PetActionClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated petaction/_operations/_operations.pyclass _PetActionClientOperationsMixin:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom new_pet_store.food import FoodClientfrom new_pet_store.pet_action import PetActionClient
client1 = FoodClient()client2 = PetActionClient()
client1.feed()client2.pet()// TODOimport { FoodClient, PetActionClient } from "@azure/package-name";
const foodClient = new FoodClient();const petActionClient = new PetActionClient();
foodClient.feed();petActionClient.pet();package newstore.food;
// Client builder class@ServiceClientBuilder(serviceClients = { FoodClient.class, FoodAsyncClient.class })public final class FoodClientBuilder implements HttpTrait<FoodClientBuilder>, ConfigurationTrait<FoodClientBuilder>, EndpointTrait<FoodClientBuilder> {
public FoodClientBuilder();
public FoodClient buildClient();}
// Client class@ServiceClient(builder = FoodClientBuilder.class)public final class FoodClient { public void feed();}
package newstore.petaction;
// Client builder class@ServiceClientBuilder(serviceClients = { PetActionClient.class, PetActionAsyncClient.class })public final class PetActionClientBuilder implements HttpTrait<PetActionClientBuilder>, ConfigurationTrait<PetActionClientBuilder>, EndpointTrait<PetActionClientBuilder> {
public PetActionClientBuilder();
public PetActionClient buildClient();}
// Client class@ServiceClient(builder = PetActionClientBuilder.class)public final class PetActionClient { public void pet();}
// Usageimport newpetstore.food.FoodClient;import newpetstore.food.FoodClientBuilder;import newpetstore.petaction.PetActionClient;import newpetstore.petaction.PetActionClientBuilder;
FoodClient foodClient = new FoodClientBuilder().buildClient();foodClient.feed();
PetActionClient petActionClient = new PetActionClientBuilder().buildClient();petActionClient.pet();// generated food_client.gotype FoodClient struct {}
func NewFoodClient() *FoodClient{ return &FoodClient{}}
func (client *FoodClient) Feed(ctx context.Context, options *FoodClientFeedOptions) (FoodClientFeedResponse, error) {}
// generated pet_action_client.gopackage newpetstore
type PetActionClient struct {}
func NewPetActionClient() *PetActionClient{ return &PetActionClient{}}
func (client *PetActionClient) Pet(ctx context.Context, options *PetActionClientPetOptions) (PetActionClientPetResponse, error) {}
// generated options.gotype FoodClientFeedOptions struct {}type PetActionClientPetOptions struct {}
// generated response.gotype FoodClientFeedResponse struct {}type PetActionClientPetResponse struct {}
// Usage SamplefoodClient := NewFoodClient()foodClient.Feed(context.Background(), &FoodClientFeedOptions{})petClient := NewPetActionClient()petClient.Pet(context.Background(), &PetActionClientPetOptions{})Splitting the Operations into Two Clients and Having Clients in Different Namespaces
Section titled “Splitting the Operations into Two Clients and Having Clients in Different Namespaces”Two clients that separate the operations can be declared using the @client decorator of typespec-client-generator-core:
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
namespace PetStoreRenamed; // this namespace will be the namespace of the clients and sub clients defined in this customization file
@client({ name: "FoodClient", service: PetStore,})interface Client1 { feed is PetStore.feed;}
@client({ name: "PetActionClient", service: PetStore,})@clientNamespace("PetStoreRenamed.SubNamespace") // use @clientNamespace to specify the namespace of the clientinterface Client2 { pet is PetStore.pet;}# generated _client.pyclass FoodClient(_FoodClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated _operations/_operations.pyclass _FoodClientOperationsMixin:
@distributed_trace def feed(self, **kwargs: Any) -> None:
# generated subnamespace/_client.pyclass PetActionClient(_PetActionClientOperationsMixin): def __init__(self, endpoint: str, **kwargs: Any) -> None: ...
# generated subnamespace/_operations/_operations.pyclass _PetActionClientOperationsMixin:
@distributed_trace def pet(self, **kwargs: Any) -> None:
#usage samplefrom pet_store_renamed import FoodClientfrom pet_store_renamed.sub_namespace import PetActionClient
client1 = FoodClient()client2 = PetActionClient()
client1.feed()client2.pet()using PetStoreRenamed;using PetStoreRenamed.SubNamespace;
SubNamespacePetActionClient petActionClient = new SubNamespacePetActionClient();FoodClient foodClient = new FoodClient();
petActionClient.Pet();foodClient.Feed();// JS CodeGen api layerexport async function feed( context: Client, options: FeedOptionalParams = { requestOptions: {} },): Promise<void>;
export async function pet( context: Client, options: PetOptionalParams = { requestOptions: {} },): Promise<void>;
// JS CodeGen classical client layerexport class PetActionClient { pet(options: PetOptionalParams = { requestOptions: {} }): Promise<void>;}
export class FoodClient { feed(options: FeedOptionalParams = { requestOptions: {} }): Promise<void>;}
// sampleimport { FoodClient, PetActionClient } from "@azure/package-name";
const foodClient = new FoodClient();const petActionClient = new PetActionClient();
foodClient.feed();petActionClient.pet();package petstorerenamed;
// Client builder class@ServiceClientBuilder(serviceClients = { FoodClient.class, FoodAsyncClient.class })public final class FoodClientBuilder implements HttpTrait<FoodClientBuilder>, ConfigurationTrait<FoodClientBuilder>, EndpointTrait<FoodClientBuilder> {
public FoodClientBuilder();
public FoodClient buildClient();}
// Client class@ServiceClient(builder = FoodClientBuilder.class)public final class FoodClient { public void feed();}
package petstorerenamed.subnamespace;
// Client builder class@ServiceClientBuilder(serviceClients = { PetActionClient.class, PetActionAsyncClient.class })public final class PetActionClientBuilder implements HttpTrait<PetActionClientBuilder>, ConfigurationTrait<PetActionClientBuilder>, EndpointTrait<PetActionClientBuilder> {
public PetActionClientBuilder();
public PetActionClient buildClient();}
// Client class@ServiceClient(builder = PetActionClientBuilder.class)public final class PetActionClient { public void pet();}
// Usageimport petstorerenamed.FoodClient;import petstorerenamed.FoodClientBuilder;import petstorerenamed.subnamespace.PetActionClient;import petstorerenamed.subnamespace.PetActionClientBuilder;
FoodClient foodClient = new FoodClientBuilder().buildClient();PetActionClient petActionClient = new PetActionClientBuilder().buildClient();
foodClient.feed();petActionClient.pet();// generated food_client.gotype FoodClient struct {}
func NewFoodClient() *FoodClient{ return &FoodClient{}}
func (client *FoodClient) Feed(ctx context.Context, options *FoodClientFeedOptions) (FoodClientFeedResponse, error) {}
// generated pet_action_client.gopackage petstorerenamed
type PetActionClient struct {}
func NewPetActionClient() *PetActionClient{ return &PetActionClient{}}
func (client *PetActionClient) Pet(ctx context.Context, options *PetActionClientPetOptions) (PetActionClientPetResponse, error) {}
// generated options.gotype FoodClientFeedOptions struct {}type PetActionClientPetOptions struct {}
// generated response.gotype FoodClientFeedResponse struct {}type PetActionClientPetResponse struct {}
// Usage SamplefoodClient := NewFoodClient()foodClient.Feed(context.Background(), &FoodClientFeedOptions{})petClient := NewPetActionClient()petClient.Pet(context.Background(), &PetActionClientPetOptions{})Adding Client Initialization Parameters
Section titled “Adding Client Initialization Parameters”By default, we only generate our clients with initialization parameters for endpoint, credential, and apiVersion, whenever any of these are applicable.
There are cases where spec authors would like their clients to have additional input parameters.
With @clientInitialization, you can pass in additional parameters you would like your client to have, by passing in parameters option of a model.
All properties of the model will be appended to the current default list of client initialization parameters.
Additionally, these client parameters will no longer appear on service methods that previously had them as part of the method signature.
The generated code will automatically pass in the inputted value from the client init to the service.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
namespace Customizations;
model StorageClientOptions { blobName: string;}
@@clientInitialization(Storage, { parameters: StorageClientOptions, });# generated _client.pyclass StorageClient(_StorageClientOperationsMixin): def __init__(self, endpoint: str, blob_name: str, **kwargs: Any) -> None: ...
# generated _operations/_operations.pyclass _StorageClientOperationsMixin:
@distributed_trace def upload(self, **kwargs: Any) -> None:
@distributed_trace def download(self, **kwargs: Any) -> None:
#usage samplefrom storage import StorageClient
client = StorageClient(endpoint="<my-endpoint>", blob_name="myBlobName", ...)
client.upload()client.download()// TODO: how do you pass in the options modelusing Storage;
StorageClient client = new StorageClient();
client.Upload();client.Download();// TODO: how do you pass in the options modelimport { StorageClient } from "@azure/package-name";
const client = new StorageClient();
client.upload();client.download();// Client builder classpackage storage;
@ServiceClientBuilder(serviceClients = { StorageClient.class, StorageAsyncClient.class })public final class StorageClientBuilder implements HttpTrait<StorageClientBuilder>, ConfigurationTrait<StorageClientBuilder>, EndpointTrait<StorageClientBuilder> {
public StorageClientBuilder();
public StorageClientBuilder blobName(String blobName);
public StorageClient buildClient();}
// Client class@ServiceClient(builder = StorageClientBuilder.class)public final class StorageClient { public void upload(); public void download();}
// Usagepackage storage;
StorageClient client = new StorageClient() .endpoint("<my-endpoint>") .blobName("myBlobName") .buildClient();
client.upload()client.download()// generated storage_client.gotype StorageClient struct {}
func NewStorageClient() *NewStorageClient{ return &NewStorageClient{}}
func (client *StorageClient) Download(ctx context.Context, options *StorageClientDownloadOptions) (StorageClientDownloadResponse, error) {}
func (client *StorageClient) Upload(ctx context.Context, options *StorageClientUploadOptions) (StorageClientUploadResponse, error) {}
// generated options.gotype StorageClientDownloadOptions struct {}type StorageClientUploadOptions struct {}
// generated response.gotype StorageClientDownloadResponse struct {}type StorageClientUploadResponse struct {}
// Usage Sampleclient := NewStorageClient()client.Download(context.Background(), &StorageClientDownloadOptions{})client.Upload(context.Background(), &StorageClientUploadOptions{})If you want to rename the parameter name that you elevate to the client level, you can use the @paramAlias decorator.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
namespace Customizations;
model StorageClientOptions { @paramAlias("blobName") blob: string;}
@@clientInitialization(Storage, { parameters: StorageClientOptions, });# generated _client.pyclass StorageClient(_StorageClientOperationsMixin): def __init__(self, endpoint: str, blob: str, **kwargs: Any) -> None: ...
# generated _operations/_operations.pyclass _StorageClientOperationsMixin:
@distributed_trace def upload(self, **kwargs: Any) -> None:
@distributed_trace def download(self, **kwargs: Any) -> None:
#usage samplefrom storage import StorageClient
client = StorageClient(endpoint="<my-endpoint>", blob="myBlobName", ...)
client.upload()client.download()// TODO: how do you pass in the options modelusing Storage;
StorageClient client = new StorageClient();
client.Upload();client.Download();// TODO: how do you pass in the options modelimport { StorageClient } from "@azure/package-name";
const client = new StorageClient();
client.upload();client.download();// Client builder classpackage storage;
@ServiceClientBuilder(serviceClients = { StorageClient.class, StorageAsyncClient.class })public final class StorageClientBuilder implements HttpTrait<StorageClientBuilder>, ConfigurationTrait<StorageClientBuilder>, EndpointTrait<StorageClientBuilder> {
public StorageClientBuilder();
public StorageClientBuilder blob(String blob);
public StorageClient buildClient();}
// Client class@ServiceClient(builder = StorageClientBuilder.class)public final class StorageClient { public void upload(); public void download();}
// Usagepackage storage;
StorageClient client = new StorageClient() .endpoint("<my-endpoint>") .blob("myBlobName") .buildClient();
client.upload()client.download()// generated storage_client.gotype StorageClient struct {}
func NewStorageClient(internal *azcore.Client, endpoint string, blobName string) *NewStorageClient{ return &NewStorageClient{ internal: internal, endpoint: endpoint, blobName: blobName }}
func (client *StorageClient) Upload(ctx context.Context, options *StorageClientUploadOptions) (StorageClientUploadResponse, error) {}
func (client *StorageClient) Download(ctx context.Context, options *StorageClientDownloadOptions) (StorageClientDownloadResponse, error) {}
// generated options.gotype StorageClientDownloadOptions struct {}type StorageClientUploadOptions struct {}
// generated response.gotype StorageClientDownloadResponse struct {}type StorageClientUploadResponse struct {}
// Usage Sampleclient := NewStorageClient(nil,"<my-endpoint>","myBlobName")client.Upload(context.Background(), &StorageClientUploadOptions{})client.Download(context.Background(), &StorageClientDownloadOptions{})Change Sub Client Initialization Way
Section titled “Change Sub Client Initialization Way”By default, all the nested sub clients could only be initialized by parent client or sub client. There are cases where spec authors would like their sub clients could both be initialized by parent as well as individually.
With @clientInitialization, you can change the initialization way, by passing in initializedBy option of InitializedBy.individually | InitializedBy.parent value.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
namespace Customizations;
model StorageClientOptions { blobName: string;}
@@clientInitialization(Storage, { initializedBy: InitializedBy.individually | InitializedBy.parent, });NOT_SUPPORTED// TODOexport class StorageClient { download( blobName: string, options: DownloadOptionalParams = { requestOptions: {} }, ): Promise<void>;}
const client = new StorageClient();client.download("blobName");// TODO// NOT_SUPPORTEDOne Client from Multiple Services
Section titled “One Client from Multiple Services”You could define a single client that combines operations from multiple services. This is useful when you want to provide a unified client experience for related services that share a common endpoint, but require different versioning.
-
Service Array: Set all the services that you want to merge in to the
@clientdecorator’sserviceproperty (e.g.,service: [ServiceA, ServiceB]). -
Auto-Merge with
autoMergeService: true: SetautoMergeService: trueon the@clientdecorator to automatically merge all operations and sub clients from every listed service into the single client.autoMergeServicedefaults tofalse. Whenfalseor omitted, the client will have no auto-populated operations — you would need to define child@clientdecorators or useisto map operations explicitly. -
Versioning: Each service’s API versions are resolved independently from its own
@versioneddefinition. TCGC always uses the latest version for each service. No@useDependencyis needed. -
Sub client Structure: When
autoMergeService: trueis set, operations and sub clients will be auto merged into the single client (based on operations, interfaces, or namespaces from the original services). -
Sub client Merging: If multiple services have nested namespaces or interfaces with the same name, TCGC will automatically merge them into a single sub client. The merged sub client will have empty
apiVersionsand astringtype for the API version parameter, and will contain operations from all the services. -
@clientLocation with Multiple Services: You can use
@clientLocationto move operations from different services to the same sub client. The resulting sub client will have emptyapiVersionsand astringtype for the API version parameter, allowing it to handle operations with different API versions.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
@client({ name: "CombineClient", service: [ServiceA, ServiceB], autoMergeService: true,})namespace CombineClient;# generated _client.pyclass CombineClient: def __init__(self, endpoint: str, **kwargs: Any) -> None: self.ai = AIOperations(endpoint=endpoint, **kwargs) self.bi = BIOperations(endpoint=endpoint, **kwargs)
# generated operations/_operations.pyclass AIOperations: def __init__(self, client, api_version: str = "av2") -> None: ...
@distributed_trace def a_test(self, **kwargs: Any) -> None: ...
class BIOperations: def __init__(self, client, api_version: str = "bv2") -> None: ...
@distributed_trace def b_test(self, **kwargs: Any) -> None: ...
# usage samplefrom combine_client import CombineClient
client = CombineClient(endpoint="<my-endpoint>")client.ai.a_test() # uses api-version av2client.bi.b_test() # uses api-version bv2using CombineClient;
// The combined client with sub clients for each serviceCombineClient client = new CombineClient(new Uri("<my-endpoint>"));
// AI operations use ServiceA's api-version (av2)client.GetAIClient().ATest();
// BI operations use ServiceB's api-version (bv2)client.GetBIClient().BTest();import { CombineClient } from "@azure/package-name";
const client = new CombineClient("<my-endpoint>");
// AI operations use ServiceA's api-version (av2)client.ai.aTest();
// BI operations use ServiceB's api-version (bv2)client.bi.bTest();// Client builder classpackage combineclient;
@ServiceClientBuilder( serviceClients = { AIClient.class, BIClient.class, AIAsyncClient.class, BIAsyncClient.class })public final class CombineClientBuilder implements HttpTrait<CombineClientBuilder>, ConfigurationTrait<CombineClientBuilder>, EndpointTrait<CombineClientBuilder> {
public CombineClientBuilder();
public AIClient buildAIClient(); public BIClient buildBIClient();}
// Client classes@ServiceClient(builder = CombineClientBuilder.class)public final class AIClient { // Uses ServiceA's api-version (av2) public void aTest();}
@ServiceClient(builder = CombineClientBuilder.class)public final class BIClient { // Uses ServiceB's api-version (bv2) public void bTest();}
// UsageCombineClientBuilder builder = new CombineClientBuilder() .endpoint("<my-endpoint>");
AIClient aiClient = builder.buildAIClient();aiClient.aTest(); // uses api-version av2
BIClient biClient = builder.buildBIClient();biClient.bTest(); // uses api-version bv2// generated combine_client.gotype CombineClient struct {}
func NewCombineClient(endpoint string) *CombineClient { return &CombineClient{}}
func (client *CombineClient) NewAIClient() *AIClient { return &AIClient{}}
func (client *CombineClient) NewBIClient() *BIClient { return &BIClient{}}
// generated ai_client.gotype AIClient struct {}
// Uses ServiceA's api-version (av2)func (client *AIClient) ATest(ctx context.Context, options *AIClientATestOptions) (AIClientATestResponse, error) {}
// generated bi_client.gotype BIClient struct {}
// Uses ServiceB's api-version (bv2)func (client *BIClient) BTest(ctx context.Context, options *BIClientBTestOptions) (BIClientBTestResponse, error) {}
// generated options.gotype AIClientATestOptions struct {}type BIClientBTestOptions struct {}
// generated response.gotype AIClientATestResponse struct {}type BIClientBTestResponse struct {}
// Usage SamplecombineClient := NewCombineClient("<my-endpoint>")aiClient := combineClient.NewAIClient()aiClient.ATest(context.Background(), &AIClientATestOptions{}) // uses api-version av2biClient := combineClient.NewBIClient()biClient.BTest(context.Background(), &BIClientBTestOptions{}) // uses api-version bv2Mixing Multi-Service and Single-Service Clients
Section titled “Mixing Multi-Service and Single-Service Clients”You can combine multiple services into one client while keeping another service as a separate client. This is useful when some services are closely related and should be accessed through a unified client, while others are independent enough to warrant their own client.
Set autoMergeService: true on any client that should automatically pull in all operations from its service(s). A multi-service client uses service: [ServiceA, ServiceB] with autoMergeService: true to merge everything, while a single-service client uses service: ServiceC with autoMergeService: true to get default behavior.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
// Multi-service client combining ServiceA and ServiceB@client({ name: "CombinedABClient", service: [ServiceA, ServiceB], autoMergeService: true,})namespace CombinedABClient;
// Single-service client for ServiceC@client({ name: "ServiceCClient", service: ServiceC, autoMergeService: true,})namespace ServiceCClient;# generated _client.pyclass CombinedABClient: def __init__(self, endpoint: str, **kwargs: Any) -> None: self.operations = OperationsOperations(endpoint=endpoint, **kwargs)
class ServiceCClient: def __init__(self, endpoint: str, **kwargs: Any) -> None: self.operations = OperationsOperations(endpoint=endpoint, **kwargs)
# usage samplefrom combined_ab_client import CombinedABClientfrom service_c_client import ServiceCClient
# Combined client for ServiceA and ServiceBcombined_client = CombinedABClient(endpoint="<my-endpoint>")combined_client.operations.op_a() # From ServiceAcombined_client.operations.op_b() # From ServiceB
# Separate client for ServiceCservice_c_client = ServiceCClient(endpoint="<my-endpoint>")service_c_client.operations.op_c()// Combined client for ServiceA and ServiceBCombinedABClient combinedClient = new CombinedABClient(new Uri("<my-endpoint>"));combinedClient.GetOperationsClient().OpA(); // From ServiceAcombinedClient.GetOperationsClient().OpB(); // From ServiceB
// Separate client for ServiceCServiceCClient serviceCClient = new ServiceCClient(new Uri("<my-endpoint>"));serviceCClient.GetOperationsClient().OpC();import { CombinedABClient } from "@azure/combined-ab";import { ServiceCClient } from "@azure/service-c";
// Combined client for ServiceA and ServiceBconst combinedClient = new CombinedABClient("<my-endpoint>");combinedClient.operations.opA(); // From ServiceAcombinedClient.operations.opB(); // From ServiceB
// Separate client for ServiceCconst serviceCClient = new ServiceCClient("<my-endpoint>");serviceCClient.operations.opC();// Combined client builder for ServiceA and ServiceBCombinedABClientBuilder combinedBuilder = new CombinedABClientBuilder() .endpoint("<my-endpoint>");
OperationsClient operationsClient = combinedBuilder.buildOperationsClient();operationsClient.opA(); // From ServiceAoperationsClient.opB(); // From ServiceB
// Separate client for ServiceCServiceCClientBuilder serviceCBuilder = new ServiceCClientBuilder() .endpoint("<my-endpoint>");
ServiceCOperationsClient serviceCOps = serviceCBuilder.buildOperationsClient();serviceCOps.opC();// Combined client for ServiceA and ServiceBcombinedClient := NewCombinedABClient("<my-endpoint>")opsClient := combinedClient.NewOperationsClient()opsClient.OpA(context.Background(), &OperationsClientOpAOptions{}) // From ServiceAopsClient.OpB(context.Background(), &OperationsClientOpBOptions{}) // From ServiceB
// Separate client for ServiceCserviceCClient := NewServiceCClient("<my-endpoint>")serviceCOps := serviceCClient.NewOperationsClient()serviceCOps.OpC(context.Background(), &OperationsClientOpCOptions{})Services as Direct Children (No Deep Auto-Merge)
Section titled “Services as Direct Children (No Deep Auto-Merge)”When combining multiple services, instead of auto-merging all sub clients at the root level, you can keep each service as a direct child of the root client.
The key is to omit autoMergeService (or set it to false) on the root client so it does NOT merge everything at the top level. Then, set autoMergeService: true on each child @client so that each child auto-populates from its own service. This creates a hierarchy where services remain separated under the root client.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
@client({ name: "CombineClient", service: [ServiceA, ServiceB],})namespace CombineClient { @client({ name: "ComputeClient", service: ServiceA, autoMergeService: true, }) namespace Compute;
@client({ name: "DiskClient", service: ServiceB, autoMergeService: true, }) namespace Disk;}# generated _client.pyclass CombineClient: def __init__(self, endpoint: str, **kwargs: Any) -> None: self.compute = ComputeClient(endpoint=endpoint, **kwargs) self.disk = DiskClient(endpoint=endpoint, **kwargs)
# usage samplefrom combine_client import CombineClient
client = CombineClient(endpoint="<my-endpoint>")
# Access ServiceA operations via ComputeClientclient.compute.operations.op_a()client.compute.sub_namespace.sub_op_a()
# Access ServiceB operations via DiskClientclient.disk.operations.op_b()client.disk.sub_namespace.sub_op_b()CombineClient client = new CombineClient(new Uri("<my-endpoint>"));
// Access ServiceA operations via ComputeClientclient.GetComputeClient().GetOperationsClient().OpA();client.GetComputeClient().GetSubNamespaceClient().SubOpA();
// Access ServiceB operations via DiskClientclient.GetDiskClient().GetOperationsClient().OpB();client.GetDiskClient().GetSubNamespaceClient().SubOpB();import { CombineClient } from "@azure/package-name";
const client = new CombineClient("<my-endpoint>");
// Access ServiceA operations via ComputeClientclient.compute.operations.opA();client.compute.subNamespace.subOpA();
// Access ServiceB operations via DiskClientclient.disk.operations.opB();client.disk.subNamespace.subOpB();CombineClientBuilder builder = new CombineClientBuilder() .endpoint("<my-endpoint>");
// Access ServiceA operations via ComputeClientComputeOperationsClient computeOps = builder.buildComputeOperationsClient();computeOps.opA();
ComputeSubNamespaceClient computeSub = builder.buildComputeSubNamespaceClient();computeSub.subOpA();
// Access ServiceB operations via DiskClientDiskOperationsClient diskOps = builder.buildDiskOperationsClient();diskOps.opB();
DiskSubNamespaceClient diskSub = builder.buildDiskSubNamespaceClient();diskSub.subOpB();combineClient := NewCombineClient("<my-endpoint>")
// Access ServiceA operations via ComputeClientcomputeClient := combineClient.NewComputeClient()computeOps := computeClient.NewOperationsClient()computeOps.OpA(context.Background(), &OperationsClientOpAOptions{})computeSub := computeClient.NewSubNamespaceClient()computeSub.SubOpA(context.Background(), &SubNamespaceClientSubOpAOptions{})
// Access ServiceB operations via DiskClientdiskClient := combineClient.NewDiskClient()diskOps := diskClient.NewOperationsClient()diskOps.OpB(context.Background(), &OperationsClientOpBOptions{})diskSub := diskClient.NewSubNamespaceClient()diskSub.SubOpB(context.Background(), &SubNamespaceClientSubOpBOptions{})Fully Customized Client Hierarchy from Multiple Services
Section titled “Fully Customized Client Hierarchy from Multiple Services”For maximum flexibility, you can fully customize how operations from different services are organized into a client hierarchy. This uses nested @client decorators with explicit operation mapping via the is keyword.
In this approach, autoMergeService is not set (defaults to false) on any client — neither the root nor the children. Instead of auto-populating from services, each child @client explicitly declares its operations using is references (e.g., opA is ServiceA.Operations.opA). This gives you full control over which operations go where, including the ability to mix operations from different services into a single sub client.
import "./main.tsp";import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
@client({ name: "CustomClient", service: [ServiceA, ServiceB],})namespace CustomClient { // Custom sub client combining operations from both services @client({ name: "SharedOperations", service: [ServiceA, ServiceB], }) interface SharedOperations { opA is ServiceA.Operations.opA; opB is ServiceB.Operations.opB; }
// Custom sub client with operations from ServiceA only @client({ name: "ServiceAOnly", service: ServiceA, }) interface ServiceAOnly { subOpA is ServiceA.SubNamespace.subOpA; }
// Custom sub client with operations from ServiceB only @client({ name: "ServiceBOnly", service: ServiceB, }) interface ServiceBOnly { subOpB is ServiceB.SubNamespace.subOpB; }}# generated _client.pyclass CustomClient: def __init__(self, endpoint: str, **kwargs: Any) -> None: self.shared_operations = SharedOperationsOperations(endpoint=endpoint, **kwargs) self.service_a_only = ServiceAOnlyOperations(endpoint=endpoint, **kwargs) self.service_b_only = ServiceBOnlyOperations(endpoint=endpoint, **kwargs)
# usage samplefrom custom_client import CustomClient
client = CustomClient(endpoint="<my-endpoint>")
# Access shared operations from both servicesclient.shared_operations.op_a() # Uses ServiceA's API versionclient.shared_operations.op_b() # Uses ServiceB's API version
# Access ServiceA-only operationsclient.service_a_only.sub_op_a()
# Access ServiceB-only operationsclient.service_b_only.sub_op_b()CustomClient client = new CustomClient(new Uri("<my-endpoint>"));
// Access shared operations from both servicesclient.GetSharedOperationsClient().OpA(); // Uses ServiceA's API versionclient.GetSharedOperationsClient().OpB(); // Uses ServiceB's API version
// Access ServiceA-only operationsclient.GetServiceAOnlyClient().SubOpA();
// Access ServiceB-only operationsclient.GetServiceBOnlyClient().SubOpB();import { CustomClient } from "@azure/package-name";
const client = new CustomClient("<my-endpoint>");
// Access shared operations from both servicesclient.sharedOperations.opA(); // Uses ServiceA's API versionclient.sharedOperations.opB(); // Uses ServiceB's API version
// Access ServiceA-only operationsclient.serviceAOnly.subOpA();
// Access ServiceB-only operationsclient.serviceBOnly.subOpB();CustomClientBuilder builder = new CustomClientBuilder() .endpoint("<my-endpoint>");
// Access shared operations from both servicesSharedOperationsClient sharedOps = builder.buildSharedOperationsClient();sharedOps.opA(); // Uses ServiceA's API versionsharedOps.opB(); // Uses ServiceB's API version
// Access ServiceA-only operationsServiceAOnlyClient serviceAOnly = builder.buildServiceAOnlyClient();serviceAOnly.subOpA();
// Access ServiceB-only operationsServiceBOnlyClient serviceBOnly = builder.buildServiceBOnlyClient();serviceBOnly.subOpB();customClient := NewCustomClient("<my-endpoint>")
// Access shared operations from both servicessharedOps := customClient.NewSharedOperationsClient()sharedOps.OpA(context.Background(), &SharedOperationsClientOpAOptions{}) // Uses ServiceA's API versionsharedOps.OpB(context.Background(), &SharedOperationsClientOpBOptions{}) // Uses ServiceB's API version
// Access ServiceA-only operationsserviceAOnly := customClient.NewServiceAOnlyClient()serviceAOnly.SubOpA(context.Background(), &ServiceAOnlyClientSubOpAOptions{})
// Access ServiceB-only operationsserviceBOnly := customClient.NewServiceBOnlyClient()serviceBOnly.SubOpB(context.Background(), &ServiceBOnlyClientSubOpBOptions{})