Skip to content

[tcgc] one client multiple services#3460

Merged
iscai-msft merged 24 commits intoAzure:mainfrom
iscai-msft:tcgc/multiServiceOneClient
Nov 21, 2025
Merged

[tcgc] one client multiple services#3460
iscai-msft merged 24 commits intoAzure:mainfrom
iscai-msft:tcgc/multiServiceOneClient

Conversation

@iscai-msft
Copy link
Contributor

@iscai-msft iscai-msft commented Oct 30, 2025

fixes #3536, fixes #3537

@microsoft-github-policy-service microsoft-github-policy-service bot added the lib:tcgc Issues for @azure-tools/typespec-client-generator-core library label Oct 30, 2025
@azure-sdk
Copy link
Collaborator

azure-sdk commented Oct 30, 2025

All changed packages have been documented.

  • @azure-tools/typespec-client-generator-core
Show changes

@azure-tools/typespec-client-generator-core - feature ✏️

Add support to define one client from multiple services. Api versions for services will rest on the subclient

@azure-sdk
Copy link
Collaborator

azure-sdk commented Oct 30, 2025

You can try these changes here

🛝 Playground 🌐 Website

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 30, 2025

Open in StackBlitz

npm i https://pkg.pr.new/Azure/typespec-azure/@azure-tools/typespec-client-generator-core@3460

commit: 9ed2b77

Comment on lines 158 to +161
this.apiVersion !== undefined &&
this.apiVersion !== "latest" &&
this.apiVersion !== "all" &&
!this.__packageVersions.includes(this.apiVersion)
!serviceVersions.includes(this.apiVersion)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This config could only be used for one service. How could this work for multiple service's version?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may need to think about how to specific multiple service's api version in the config.

@iscai-msft iscai-msft marked this pull request as ready for review November 20, 2025 20:23
@iscai-msft iscai-msft enabled auto-merge November 20, 2025 22:21
@iscai-msft iscai-msft added this pull request to the merge queue Nov 21, 2025
Merged via the queue into Azure:main with commit a872ce2 Nov 21, 2025
26 checks passed
@iscai-msft iscai-msft deleted the tcgc/multiServiceOneClient branch November 21, 2025 00:55
// operations directly under the group
const operations = [...group.type.operations.values()];

// For interfaces that extend other interfaces, also collect operations from the source interfaces
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it a bug from TypeSpec? This seems a hack to get back the operations that raw type graph does not have. If it only happens when having versioning, I doubt if it is a versioning mutator issue.

const diagnostics = createDiagnosticCollector();

const packageVersions = context.getPackageVersions();
const packageVersions = context.getApiVersions();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail for example loading since different service have different version.

Comment on lines +853 to +864
// Find the service that has versioning information
// In single-service scenarios, this should be the service with @versioned
// In multi-service without @useDependency, use the first service with versions
let targetService = services[0].type;
for (const service of services) {
const versions = getVersions(context.program, service.type)[1];
if (versions) {
targetService = service.type;
break;
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, for multiple service, we always need to define @client with parent to build the hierarchy?
If so, here we could just keep the original logic. I'm not get the point to find a versioned service for multi-service.
If not, I think we could generate paralleled clients with these services.

Comment on lines +230 to +234
reportDiagnostic(this.program, {
code: "multiple-services-require-use-dependency",
format: { services: services.map((s) => s.type.name).join(", ") },
target: services[0].type,
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If not meet the case, shall we return directly?

Comment on lines +283 to 291
const cachedVersions = this.__serviceToVersions.get(service);
if (cachedVersions?.length) {
return cachedVersions;
}

const versions = getVersions(program, service)[1]?.getVersions();
if (!versions) {
this.__packageVersions = [];
return this.__packageVersions;
return [];
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For services that without versioning, we should also save the cache.

Comment on lines +201 to +208
if (!parent && client.kind === "SdkClient" && client.parent) {
const parentRaw = context.__rawClientsOperationGroupsCache?.get(client.parent) as
| SdkClient
| undefined;
parent = context.__clientTypesCache?.find((c) => c.__raw === parentRaw) as
| SdkClientType<TServiceOperation>
| undefined;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't prefer to mix the client hierarchy build into the SDK type creation section. It's better to do it in the cache process.

}
}

// Check for multi-service scenario with @useDependency
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering why the API parameter no longer poped up from the operation level's parameter for multi-service cases? I believe only the top-level client should have special logic.

return diagnostics.wrap(sdkPackage);
}

function createClients<TServiceOperation extends SdkServiceOperation>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this client hierarchy build process into cache builder section. I prefer after we get the client hierarchy info, all the following calculation does not have special logic for multi-service scenario. The only exception could be API version cache builder.

);
});

it("one client from multiple services", async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are diagnostic error for these test cases. See playground. We need to change rule of invalid-initialized-by.

tadelesh pushed a commit that referenced this pull request Dec 4, 2025
iscai-msft pushed a commit to iscai-msft/typespec-azure that referenced this pull request Dec 9, 2025
github-merge-queue bot pushed a commit that referenced this pull request Dec 9, 2025
This reverts commit a872ce2.

---------

Co-authored-by: iscai-msft <isabellavcai@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lib:tcgc Issues for @azure-tools/typespec-client-generator-core library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multiples services for one client TCGC Implementation Multiples services for one client TCGC Author doc

4 participants