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, the first namespace with the @service
decorator is generated as a 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 operation groups with a hierarchical structure. The sequence of operation groups 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 an operation group 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, operation groups can only be initialized by the root client or their parent operation group.
Different languages organize clients and operation groups 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 Operation Groups
Section titled “Client with One-Layer Child Operation Groups”The PetStore includes two operation groups: 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 Operation Groups
Section titled “Client with Multi-Layer Child Operation Groups”PetStore
has three operation groups: Billings
(from an interface), Pets
(from a sub-namespace), and Actions
(from an interface). Pets
also contains a nested operation group, 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 open(self, **kwargs: Any) -> None:
@distributed_trace def close(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
and @operationGroup
to restructure the client hierarchy.
These two ways should not be used together. If so, @client
and @operationGroup
will take precedence over @clientLocation
.
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
and @operationGroup
decorators allow 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
.
Similarly, the operation group’s SDK namespace follows the same logic for @operationGroup
. You can override this using @clientNamespace
if needed.
The sequence of clients and operation groups is determined by the order of the @client
and @operationGroup
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 NewPetStorePetsActionsClient() *PetStorePetsActionsClient{ return &PetStorePetsActionsClient{}}
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_SUPPORTED
Splitting 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 operation groups 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 Operation Groups
Section titled “One Client and Two Operation Groups”Two clients that separate the operations can be declared using the @client
decorator and the @operationGroup
decorator 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 operation groups 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()
// TODO
import { 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 operation groups 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();
// Modular api layerexport async function feed( context: Client, options: FeedOptionalParams = { requestOptions: {} },): Promise<void>;
export async function pet( context: Client, options: PetOptionalParams = { requestOptions: {} },): Promise<void>;
// Modular 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 Operation Group Initialization Way
Section titled “Change Operation Group Initialization Way”By default, all the nested operation group could only be initialized by parent client or operation group. There are cases where spec authors would like their operation groups 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
// TODO
export class StorageClient { download( blobName: string, options: DownloadOptionalParams = { requestOptions: {} }, ): Promise<void>;}
const client = new StorageClient();client.download("blobName");
// TODO
// NOT_SUPPORTED