From ec9594f94993fa42d9a706935fa725a54c7cf6a0 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Mon, 23 Feb 2026 15:31:31 -0800 Subject: [PATCH 01/12] fix: add logic to check for IAM RPC methods within the service before adding mixin to avoid generating duplicate methods --- .../typescript/src/generator.ts | 21 ++++++++++++++++-- .../typescript/src/schema/api.ts | 22 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/generator/gapic-generator-typescript/typescript/src/generator.ts b/generator/gapic-generator-typescript/typescript/src/generator.ts index ac490f404..9892ed8d9 100644 --- a/generator/gapic-generator-typescript/typescript/src/generator.ts +++ b/generator/gapic-generator-typescript/typescript/src/generator.ts @@ -19,7 +19,7 @@ import * as yaml from 'js-yaml'; import * as serializer from 'proto3-json-serializer'; import protobuf from 'protobufjs'; import type * as protos from '../../protos/index.js'; -import protoJson from '../../protos/protos.json' assert {type: 'json'}; +import protoJson from '../../protos/protos.json' with { type: 'json' }; import * as url from 'url'; import {API} from './schema/api.js'; import {processTemplates} from './templater.js'; @@ -163,13 +163,30 @@ export class Generator { const content = fs.readFileSync(filename, 'utf8'); const info = yaml.load(content) as ServiceYaml; this.serviceYaml = info; - const serviceMixins = []; + let serviceMixins: string[] = []; for (let i = 0; i < info.apis?.length || 0; i++) { const api = info.apis[i]; for (const [, value] of Object.entries(api)) { serviceMixins.push(value); } } + if (serviceMixins.includes('google.iam.v1.IAMPolicy')) { + // Check if any of the services in the protos have SetIamPolicy, GetIamPolicy, or TestIamPermissions methods. + // If so, then remove the IAMPolicy mixin from the service yaml file to avoid duplicates. + const methods = API.getServiceMethods( + this.request.protoFile, + this.request.fileToGenerate, + ); + if ( + methods.has('SetIamPolicy') || + methods.has('GetIamPolicy') || + methods.has('TestIamPermissions') + ) { + serviceMixins = serviceMixins.filter( + m => m !== 'google.iam.v1.IAMPolicy' + ); + } + } this.serviceYaml.apis = serviceMixins; } // override if needed diff --git a/generator/gapic-generator-typescript/typescript/src/schema/api.ts b/generator/gapic-generator-typescript/typescript/src/schema/api.ts index 7777b7e13..8c0300390 100644 --- a/generator/gapic-generator-typescript/typescript/src/schema/api.ts +++ b/generator/gapic-generator-typescript/typescript/src/schema/api.ts @@ -87,6 +87,28 @@ export class API { return filteredProtos; } + static getServiceMethods( + fds: protos.google.protobuf.IFileDescriptorProto[], + filesToGenerate: string[], + ) { + const methods = new Set(); + const filesToGenerateSet = new Set(filesToGenerate); + for (const fd of fds) { + if (filesToGenerateSet.has(fd.name!) && fd.service) { + for (const service of fd.service) { + if (service.method) { + for (const method of service.method) { + if (method.name) { + methods.add(method.name); + } + } + } + } + } + } + return methods; + } + constructor( fileDescriptors: protos.google.protobuf.IFileDescriptorProto[], packageName: string, From 675c640d5d9a7a81d662da9af9f418ea4e9d8976 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Mon, 23 Feb 2026 15:41:45 -0800 Subject: [PATCH 02/12] fix: update formatting --- .../gapic-generator-typescript/typescript/src/generator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generator/gapic-generator-typescript/typescript/src/generator.ts b/generator/gapic-generator-typescript/typescript/src/generator.ts index 9892ed8d9..e6c0548e5 100644 --- a/generator/gapic-generator-typescript/typescript/src/generator.ts +++ b/generator/gapic-generator-typescript/typescript/src/generator.ts @@ -19,7 +19,7 @@ import * as yaml from 'js-yaml'; import * as serializer from 'proto3-json-serializer'; import protobuf from 'protobufjs'; import type * as protos from '../../protos/index.js'; -import protoJson from '../../protos/protos.json' with { type: 'json' }; +import protoJson from '../../protos/protos.json' with {type: 'json'}; import * as url from 'url'; import {API} from './schema/api.js'; import {processTemplates} from './templater.js'; @@ -183,7 +183,7 @@ export class Generator { methods.has('TestIamPermissions') ) { serviceMixins = serviceMixins.filter( - m => m !== 'google.iam.v1.IAMPolicy' + m => m !== 'google.iam.v1.IAMPolicy', ); } } From 30f7563fc3d707eedc486ce446840e98016e68b8 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Tue, 10 Mar 2026 16:15:52 -0700 Subject: [PATCH 03/12] resetoring changes --- .../typescript/src/generator.ts | 23 +++--------------- .../typescript/src/schema/api.ts | 24 +------------------ 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/generator/gapic-generator-typescript/typescript/src/generator.ts b/generator/gapic-generator-typescript/typescript/src/generator.ts index e6c0548e5..81e5b1be1 100644 --- a/generator/gapic-generator-typescript/typescript/src/generator.ts +++ b/generator/gapic-generator-typescript/typescript/src/generator.ts @@ -19,7 +19,7 @@ import * as yaml from 'js-yaml'; import * as serializer from 'proto3-json-serializer'; import protobuf from 'protobufjs'; import type * as protos from '../../protos/index.js'; -import protoJson from '../../protos/protos.json' with {type: 'json'}; +import protoJson from '../../protos/protos.json' assert {type: 'json'}; import * as url from 'url'; import {API} from './schema/api.js'; import {processTemplates} from './templater.js'; @@ -163,30 +163,13 @@ export class Generator { const content = fs.readFileSync(filename, 'utf8'); const info = yaml.load(content) as ServiceYaml; this.serviceYaml = info; - let serviceMixins: string[] = []; + const serviceMixins = []; for (let i = 0; i < info.apis?.length || 0; i++) { const api = info.apis[i]; for (const [, value] of Object.entries(api)) { serviceMixins.push(value); } } - if (serviceMixins.includes('google.iam.v1.IAMPolicy')) { - // Check if any of the services in the protos have SetIamPolicy, GetIamPolicy, or TestIamPermissions methods. - // If so, then remove the IAMPolicy mixin from the service yaml file to avoid duplicates. - const methods = API.getServiceMethods( - this.request.protoFile, - this.request.fileToGenerate, - ); - if ( - methods.has('SetIamPolicy') || - methods.has('GetIamPolicy') || - methods.has('TestIamPermissions') - ) { - serviceMixins = serviceMixins.filter( - m => m !== 'google.iam.v1.IAMPolicy', - ); - } - } this.serviceYaml.apis = serviceMixins; } // override if needed @@ -405,4 +388,4 @@ export class Generator { ).finish(); process.stdout.write(outputBuffer); } -} +} \ No newline at end of file diff --git a/generator/gapic-generator-typescript/typescript/src/schema/api.ts b/generator/gapic-generator-typescript/typescript/src/schema/api.ts index 8c0300390..af9e07bb5 100644 --- a/generator/gapic-generator-typescript/typescript/src/schema/api.ts +++ b/generator/gapic-generator-typescript/typescript/src/schema/api.ts @@ -87,28 +87,6 @@ export class API { return filteredProtos; } - static getServiceMethods( - fds: protos.google.protobuf.IFileDescriptorProto[], - filesToGenerate: string[], - ) { - const methods = new Set(); - const filesToGenerateSet = new Set(filesToGenerate); - for (const fd of fds) { - if (filesToGenerateSet.has(fd.name!) && fd.service) { - for (const service of fd.service) { - if (service.method) { - for (const method of service.method) { - if (method.name) { - methods.add(method.name); - } - } - } - } - } - } - return methods; - } - constructor( fileDescriptors: protos.google.protobuf.IFileDescriptorProto[], packageName: string, @@ -310,4 +288,4 @@ function getResourceDatabase( } } return [allResourceDatabase, resourceDatabase]; -} +} \ No newline at end of file From 7095b8e9fa18607a3d293aa689b80581de0f3dd7 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 15:46:32 -0700 Subject: [PATCH 04/12] Update the method logic for the service client nunjucks templates to check for method name conflicts with the IAM and Location mixins before generating the methods. This is to avoid generating duplicate methods in cases where the service already has methods with the same names as those provided by the mixins. Based on https://google.aip.dev/client-libraries/4234#overriding-a-duplicate-rpc, some mixin methods may be defined within the service file, but not necessarily all. The generator will silently skip the duplicate mixin methods for the IAM and Location mixins. --- .../templates/cjs/typescript_gapic/_iam.njk | 11 ++++++++++ .../cjs/typescript_gapic/_locations.njk | 7 ++++++ .../src/$version/$service_client.ts.njk | 19 ++++++++++++++-- .../templates/esm/typescript_gapic/_iam.njk | 11 ++++++++++ .../esm/typescript_gapic/_locations.njk | 8 +++++++ .../esm/src/$version/$service_client.ts.njk | 22 ++++++++++++++++--- 6 files changed, 73 insertions(+), 5 deletions(-) diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_iam.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_iam.njk index 281ad5a33..dc34955f6 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_iam.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_iam.njk @@ -5,6 +5,12 @@ IamClient is created for the client in the constructor. [setIamPolicy, getIamPolicy, testIamPermission] methods are created which is calling the corresponding methods from IamClient in google-gax. -#} +{{ getIamPolicy() }} +{{ setIamPolicy() }} +{{ testIamPermissions() }} +{%- endmacro -%} + +{%- macro getIamPolicy() -%} /** * Gets the access control policy for a resource. Returns an empty policy * if the resource exists and does not have a policy set. @@ -47,7 +53,9 @@ ):Promise<[IamProtos.google.iam.v1.Policy]> { return this.iamClient.getIamPolicy(request, options, callback); } +{%- endmacro -%} +{%- macro setIamPolicy() -%} /** * Returns permissions that a caller has on the specified resource. If the * resource does not exist, this will return an empty set of @@ -94,7 +102,9 @@ ):Promise<[IamProtos.google.iam.v1.Policy]> { return this.iamClient.setIamPolicy(request, options, callback); } +{%- endmacro -%} +{%- macro testIamPermissions() -%} /** * Returns permissions that a caller has on the specified resource. If the * resource does not exist, this will return an empty set of @@ -143,3 +153,4 @@ return this.iamClient.testIamPermissions(request, options, callback); } {%- endmacro -%} +{%- endmacro -%} diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_locations.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_locations.njk index 728b057d5..085a3db89 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_locations.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_locations.njk @@ -6,6 +6,11 @@ [getLocation, listLocations] methods are created which is calling the corresponding methods from LocationsClient in google-gax. Note that since the listLocations method is a paginated method, we default to using listLocationsAsync for ease of use. -#} +{{ getLocation() }} +{{ listLocationsAsync() }} +{%- endmacro -%} + +{%- macro getLocation() -%} /** * Gets information about a location. * @@ -45,7 +50,9 @@ ): Promise { return this.locationsClient.getLocation(request, options, callback); } +{%- endmacro -%} +{%- macro listLocationsAsync() -%} /** * Lists information about the supported locations for this service. Returns an iterable object. * diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk index da67e250f..48c040e05 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk @@ -27,10 +27,12 @@ limitations under the License. {% import "../../_namer.njk" as namer -%} {{- namer.initialize(id, service) -}} {%- set autoPopulated = false -%} +{%- set methodNames = {} %} {%- for method in service.method -%} {%- if method.autoPopulatedFields|length !== 0 %} {%- set autoPopulated = true -%} {%- endif %} + {%- do methodNames.update({(method.name.toCamelCase()): true}) -%} {%- endfor -%} import {% if (not api.legacyProtoLoad) and (autoPopulated === false) %}type {% endif %}* as gax from 'google-gax'; import type {Callback, CallOptions, Descriptors, ClientOptions @@ -1103,10 +1105,23 @@ export class {{ service.name }}Client { {%- endif %} {%- endfor %} {%- if service.IAMPolicyMixin > 0 %} -{{ iam.iamServiceMethods()}} + {%- if not methodNames['getIamPolicy'] %} + {{ iam.getIamPolicy()}} + {%- endif %} + {%- if not methodNames['setIamPolicy'] %} + {{ iam.setIamPolicy()}} + {%- endif %} + {%- if not methodNames['testIamPermissions'] %} + {{ iam.testIamPermissions()}} + {%- endif %} {% endif -%} {%- if service.LocationMixin > 0 %} -{{ location.locationServiceMethods()}} + {%- if not methodNames['getLocation'] %} + {{ location.getLocation() }} + {%- endif %} + {%- if not methodNames['listLocations'] %} + {{ location.listLocationsAsync() }} + {%- endif %} {% endif -%} {%- if service.LongRunningOperationsMixin > 0 %} {{ operations.operationsServiceMethods()}} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_iam.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_iam.njk index 281ad5a33..dc34955f6 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_iam.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_iam.njk @@ -5,6 +5,12 @@ IamClient is created for the client in the constructor. [setIamPolicy, getIamPolicy, testIamPermission] methods are created which is calling the corresponding methods from IamClient in google-gax. -#} +{{ getIamPolicy() }} +{{ setIamPolicy() }} +{{ testIamPermissions() }} +{%- endmacro -%} + +{%- macro getIamPolicy() -%} /** * Gets the access control policy for a resource. Returns an empty policy * if the resource exists and does not have a policy set. @@ -47,7 +53,9 @@ ):Promise<[IamProtos.google.iam.v1.Policy]> { return this.iamClient.getIamPolicy(request, options, callback); } +{%- endmacro -%} +{%- macro setIamPolicy() -%} /** * Returns permissions that a caller has on the specified resource. If the * resource does not exist, this will return an empty set of @@ -94,7 +102,9 @@ ):Promise<[IamProtos.google.iam.v1.Policy]> { return this.iamClient.setIamPolicy(request, options, callback); } +{%- endmacro -%} +{%- macro testIamPermissions() -%} /** * Returns permissions that a caller has on the specified resource. If the * resource does not exist, this will return an empty set of @@ -143,3 +153,4 @@ return this.iamClient.testIamPermissions(request, options, callback); } {%- endmacro -%} +{%- endmacro -%} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_locations.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_locations.njk index 728b057d5..b0c6b3d2a 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_locations.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_locations.njk @@ -6,6 +6,11 @@ [getLocation, listLocations] methods are created which is calling the corresponding methods from LocationsClient in google-gax. Note that since the listLocations method is a paginated method, we default to using listLocationsAsync for ease of use. -#} +{{ getLocation() }} +{{ listLocationsAsync() }} +{%- endmacro -%} + +{%- macro getLocation() -%} /** * Gets information about a location. * @@ -45,7 +50,9 @@ ): Promise { return this.locationsClient.getLocation(request, options, callback); } +{%- endmacro -%} +{%- macro listLocationsAsync() -%} /** * Lists information about the supported locations for this service. Returns an iterable object. * @@ -84,3 +91,4 @@ return this.locationsClient.listLocationsAsync(request, options); } {%- endmacro -%} +{%- endmacro -%} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk index 62d4d28e9..a3dda34dc 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk @@ -70,6 +70,10 @@ import {loggingUtils as logging} from 'google-gax'; const version = getJSON( path.join(dirname, '..', '..', '..', '..', 'package.json') ).version; +{%- set methodNames = {} %} +{%- for method in service.method -%} + {%- do methodNames.update({(method.name.toCamelCase()): true}) -%} +{%- endfor -%} /** {{- util.printCommentsForService(service) }} @@ -448,7 +452,6 @@ export class {{ service.name }}Client { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this._protos as any).{{api.naming.protoPackage}}.{{ service.name }}, this._opts, this._providedCustomServicePath) as Promise<{[method: string]: Function}>; - {%- set stubMethodsContent %} {%- set stubMethodsJoiner = joiner(', ') -%} {%- for method in service.method -%} @@ -1110,10 +1113,23 @@ export class {{ service.name }}Client { {%- endif %} {%- endfor %} {%- if service.IAMPolicyMixin > 0 %} -{{ iam.iamServiceMethods()}} + {%- if not methodNames['getIamPolicy'] %} + {{ iam.getIamPolicy()}} + {%- endif %} + {%- if not methodNames['setIamPolicy'] %} + {{ iam.setIamPolicy()}} + {%- endif %} + {%- if not methodNames['testIamPermissions'] %} + {{ iam.testIamPermissions()}} + {%- endif %} {% endif -%} {%- if service.LocationMixin > 0 %} -{{ location.locationServiceMethods()}} + {%- if not methodNames['getLocation'] %} + {{ location.getLocation() }} + {%- endif %} + {%- if not methodNames['listLocations'] %} + {{ location.listLocationsAsync() }} + {%- endif %} {% endif -%} {%- if service.LongRunningOperationsMixin > 0 %} {{ operations.operationsServiceMethods()}} From 45184145c4fe4c10e8129444d8b59f567821be5f Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 15:52:37 -0700 Subject: [PATCH 05/12] Update formatting --- .../gapic-generator-typescript/typescript/src/generator.ts | 2 +- .../gapic-generator-typescript/typescript/src/schema/api.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/generator/gapic-generator-typescript/typescript/src/generator.ts b/generator/gapic-generator-typescript/typescript/src/generator.ts index 81e5b1be1..ac490f404 100644 --- a/generator/gapic-generator-typescript/typescript/src/generator.ts +++ b/generator/gapic-generator-typescript/typescript/src/generator.ts @@ -388,4 +388,4 @@ export class Generator { ).finish(); process.stdout.write(outputBuffer); } -} \ No newline at end of file +} diff --git a/generator/gapic-generator-typescript/typescript/src/schema/api.ts b/generator/gapic-generator-typescript/typescript/src/schema/api.ts index af9e07bb5..7777b7e13 100644 --- a/generator/gapic-generator-typescript/typescript/src/schema/api.ts +++ b/generator/gapic-generator-typescript/typescript/src/schema/api.ts @@ -288,4 +288,4 @@ function getResourceDatabase( } } return [allResourceDatabase, resourceDatabase]; -} \ No newline at end of file +} From 74fcc77a5f3141c4e819b04c7cafe0a2fa253990 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 16:23:27 -0700 Subject: [PATCH 06/12] Update nunjucks templates formatting --- .../templates/cjs/typescript_gapic/_iam.njk | 1 - .../src/$version/$service_client.ts.njk | 14 +++++++------- .../templates/esm/typescript_gapic/_iam.njk | 1 - .../templates/esm/typescript_gapic/_locations.njk | 1 - .../esm/src/$version/$service_client.ts.njk | 14 +++++++------- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_iam.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_iam.njk index dc34955f6..967f24b83 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_iam.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/_iam.njk @@ -153,4 +153,3 @@ return this.iamClient.testIamPermissions(request, options, callback); } {%- endmacro -%} -{%- endmacro -%} diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk index 48c040e05..d7fe8066e 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk @@ -27,12 +27,12 @@ limitations under the License. {% import "../../_namer.njk" as namer -%} {{- namer.initialize(id, service) -}} {%- set autoPopulated = false -%} -{%- set methodNames = {} %} +{%- set methodNames = [] %} {%- for method in service.method -%} {%- if method.autoPopulatedFields|length !== 0 %} {%- set autoPopulated = true -%} {%- endif %} - {%- do methodNames.update({(method.name.toCamelCase()): true}) -%} + {%- do methodNames.push(method.name.toCamelCase()) -%} {%- endfor -%} import {% if (not api.legacyProtoLoad) and (autoPopulated === false) %}type {% endif %}* as gax from 'google-gax'; import type {Callback, CallOptions, Descriptors, ClientOptions @@ -1105,21 +1105,21 @@ export class {{ service.name }}Client { {%- endif %} {%- endfor %} {%- if service.IAMPolicyMixin > 0 %} - {%- if not methodNames['getIamPolicy'] %} + {%- if 'getIamPolicy' not in methodNames %} {{ iam.getIamPolicy()}} {%- endif %} - {%- if not methodNames['setIamPolicy'] %} + {%- if 'setIamPolicy' not in methodNames %} {{ iam.setIamPolicy()}} {%- endif %} - {%- if not methodNames['testIamPermissions'] %} + {%- if 'testIamPermissions' not in methodNames %} {{ iam.testIamPermissions()}} {%- endif %} {% endif -%} {%- if service.LocationMixin > 0 %} - {%- if not methodNames['getLocation'] %} + {%- if 'getLocation' not in methodNames %} {{ location.getLocation() }} {%- endif %} - {%- if not methodNames['listLocations'] %} + {%- if 'listLocations' not in methodNames %} {{ location.listLocationsAsync() }} {%- endif %} {% endif -%} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_iam.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_iam.njk index dc34955f6..967f24b83 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_iam.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_iam.njk @@ -153,4 +153,3 @@ return this.iamClient.testIamPermissions(request, options, callback); } {%- endmacro -%} -{%- endmacro -%} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_locations.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_locations.njk index b0c6b3d2a..085a3db89 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_locations.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/_locations.njk @@ -91,4 +91,3 @@ return this.locationsClient.listLocationsAsync(request, options); } {%- endmacro -%} -{%- endmacro -%} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk index a3dda34dc..a1afae133 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk @@ -70,9 +70,9 @@ import {loggingUtils as logging} from 'google-gax'; const version = getJSON( path.join(dirname, '..', '..', '..', '..', 'package.json') ).version; -{%- set methodNames = {} %} +{%- set methodNames = [] %} {%- for method in service.method -%} - {%- do methodNames.update({(method.name.toCamelCase()): true}) -%} + {%- do methodNames.push(method.name.toCamelCase()) -%} {%- endfor -%} /** @@ -1113,21 +1113,21 @@ export class {{ service.name }}Client { {%- endif %} {%- endfor %} {%- if service.IAMPolicyMixin > 0 %} - {%- if not methodNames['getIamPolicy'] %} + {%- if 'getIamPolicy' not in methodNames %} {{ iam.getIamPolicy()}} {%- endif %} - {%- if not methodNames['setIamPolicy'] %} + {%- if 'setIamPolicy' not in methodNames %} {{ iam.setIamPolicy()}} {%- endif %} - {%- if not methodNames['testIamPermissions'] %} + {%- if 'testIamPermissions' not in methodNames %} {{ iam.testIamPermissions()}} {%- endif %} {% endif -%} {%- if service.LocationMixin > 0 %} - {%- if not methodNames['getLocation'] %} + {%- if 'getLocation' not in methodNames %} {{ location.getLocation() }} {%- endif %} - {%- if not methodNames['listLocations'] %} + {%- if 'listLocations' not in methodNames %} {{ location.listLocationsAsync() }} {%- endif %} {% endif -%} From 0490c9c0aaebc49e87ad1f93a7f578780f6c6008 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 16:35:38 -0700 Subject: [PATCH 07/12] Update testing files --- .../test/gapic_$service_$version.ts.njk | 10 ++++++++++ .../esm/test/gapic_$service_$version.ts.njk | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk index cb6018680..64b2dc4a2 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk @@ -20,6 +20,10 @@ limitations under the License. {{license.license(commonParameters.copyrightYear)}} {% import "../_namer.njk" as namer -%} {{- namer.initialize(id, service) -}} +{%- set methodNames = [] %} +{%- for method in service.method -%} + {%- do methodNames.push(method.name.toCamelCase()) -%} +{%- endfor -%} import * as protos from '../protos/protos'; import * as assert from 'assert'; import * as sinon from 'sinon'; @@ -1089,6 +1093,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { {%- if (service.IAMPolicyMixin) > 0 %} {%- set IAMmethods = ['getIamPolicy', 'setIamPolicy', 'testIamPermissions'] %} {%- for method in IAMmethods %} + {%- if method not in methodNames %} describe('{{ method }}', () => { it('invokes {{ method }} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client( @@ -1204,10 +1209,12 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { .getCall(0).calledWith(request, expectedOptions, undefined)); }); }); + {%- endif %} {%- endfor %} {%- endif %} {%- if service.LocationMixin > 0 %} {%- set method = 'getLocation' %} + {%- if method not in methodNames %} describe('{{ method }}', () => { it('invokes {{ method }} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client( @@ -1314,7 +1321,9 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { .getCall(0).calledWith(request, expectedOptions, undefined)); }); }); + {%- endif %} {%- set method = 'listLocations' %} + {%- if method not in methodNames %} describe('{{ method }}Async', () => { it('uses async iteration with {{method}} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client({{- util.initClientOptions(api.rest) -}}); @@ -1395,6 +1404,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { ); }); }); + {%- endif %} {%- endif %} {%- if (service.LongRunningOperationsMixin) > 0 %} {%- set Operationsmethods = ['getOperation', 'cancelOperation', 'deleteOperation'] %} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk index 0d723c4e2..9ead618d8 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk @@ -20,6 +20,10 @@ limitations under the License. {{license.license(commonParameters.copyrightYear)}} {% import "../../_namer.njk" as namer -%} {{- namer.initialize(id, service) -}} +{%- set methodNames = [] %} +{%- for method in service.method -%} + {%- do methodNames.push(method.name.toCamelCase()) -%} +{%- endfor -%} // @ts-ignore import * as protos from '../../protos/protos.js'; import assert from 'assert'; @@ -1095,6 +1099,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { {%- if (service.IAMPolicyMixin) > 0 %} {%- set IAMmethods = ['getIamPolicy', 'setIamPolicy', 'testIamPermissions'] %} {%- for method in IAMmethods %} + {%- if method not in methodNames %} describe('{{ method }}', () => { it('invokes {{ method }} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client( @@ -1210,10 +1215,12 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { .getCall(0).calledWith(request, expectedOptions, undefined)); }); }); + {%- endif %} {%- endfor %} {%- endif %} {%- if service.LocationMixin > 0 %} {%- set method = 'getLocation' %} + {%- if method not in methodNames %} describe('{{ method }}', () => { it('invokes {{ method }} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client( @@ -1320,7 +1327,9 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { .getCall(0).calledWith(request, expectedOptions, undefined)); }); }); + {%- endif %} {%- set method = 'listLocations' %} + {%- if method not in methodNames %} describe('{{ method }}Async', () => { it('uses async iteration with {{method}} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client({{- util.initClientOptions(api.rest) -}}); @@ -1401,6 +1410,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { ); }); }); + {%- endif %} {%- endif %} {%- if (service.LongRunningOperationsMixin) > 0 %} {%- set Operationsmethods = ['getOperation', 'cancelOperation', 'deleteOperation'] %} From 399ba10cc0a1ad41e045ed3c1c46a3829372c584 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 17:47:43 -0700 Subject: [PATCH 08/12] Update relevant testing logic --- .../src/$version/$service_client.ts.njk | 14 +++++++------- .../test/gapic_$service_$version.ts.njk | 10 +++++----- .../esm/src/$version/$service_client.ts.njk | 14 +++++++------- .../esm/test/gapic_$service_$version.ts.njk | 10 +++++----- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk index d7fe8066e..2aa1cdb52 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk @@ -27,12 +27,12 @@ limitations under the License. {% import "../../_namer.njk" as namer -%} {{- namer.initialize(id, service) -}} {%- set autoPopulated = false -%} -{%- set methodNames = [] %} +{%- set methodNamesStr = "|" %} {%- for method in service.method -%} {%- if method.autoPopulatedFields|length !== 0 %} {%- set autoPopulated = true -%} {%- endif %} - {%- do methodNames.push(method.name.toCamelCase()) -%} + {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} {%- endfor -%} import {% if (not api.legacyProtoLoad) and (autoPopulated === false) %}type {% endif %}* as gax from 'google-gax'; import type {Callback, CallOptions, Descriptors, ClientOptions @@ -1105,21 +1105,21 @@ export class {{ service.name }}Client { {%- endif %} {%- endfor %} {%- if service.IAMPolicyMixin > 0 %} - {%- if 'getIamPolicy' not in methodNames %} + {%- if '|getIamPolicy|' not in methodNamesStr %} {{ iam.getIamPolicy()}} {%- endif %} - {%- if 'setIamPolicy' not in methodNames %} + {%- if '|setIamPolicy|' not in methodNamesStr %} {{ iam.setIamPolicy()}} {%- endif %} - {%- if 'testIamPermissions' not in methodNames %} + {%- if '|testIamPermissions|' not in methodNamesStr %} {{ iam.testIamPermissions()}} {%- endif %} {% endif -%} {%- if service.LocationMixin > 0 %} - {%- if 'getLocation' not in methodNames %} + {%- if '|getLocation|' not in methodNamesStr %} {{ location.getLocation() }} {%- endif %} - {%- if 'listLocations' not in methodNames %} + {%- if '|listLocations|' not in methodNamesStr %} {{ location.listLocationsAsync() }} {%- endif %} {% endif -%} diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk index 64b2dc4a2..a2f53e0f3 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk @@ -20,9 +20,9 @@ limitations under the License. {{license.license(commonParameters.copyrightYear)}} {% import "../_namer.njk" as namer -%} {{- namer.initialize(id, service) -}} -{%- set methodNames = [] %} +{%- set methodNamesStr = "|" %} {%- for method in service.method -%} - {%- do methodNames.push(method.name.toCamelCase()) -%} + {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} {%- endfor -%} import * as protos from '../protos/protos'; import * as assert from 'assert'; @@ -1093,7 +1093,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { {%- if (service.IAMPolicyMixin) > 0 %} {%- set IAMmethods = ['getIamPolicy', 'setIamPolicy', 'testIamPermissions'] %} {%- for method in IAMmethods %} - {%- if method not in methodNames %} + {%- if ("|" + method + "|") not in methodNamesStr %} describe('{{ method }}', () => { it('invokes {{ method }} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client( @@ -1214,7 +1214,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { {%- endif %} {%- if service.LocationMixin > 0 %} {%- set method = 'getLocation' %} - {%- if method not in methodNames %} + {%- if ("|" + method + "|") not in methodNamesStr %} describe('{{ method }}', () => { it('invokes {{ method }} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client( @@ -1323,7 +1323,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { }); {%- endif %} {%- set method = 'listLocations' %} - {%- if method not in methodNames %} + {%- if ("|" + method + "|") not in methodNamesStr %} describe('{{ method }}Async', () => { it('uses async iteration with {{method}} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client({{- util.initClientOptions(api.rest) -}}); diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk index a1afae133..fdc9457d9 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk @@ -70,9 +70,9 @@ import {loggingUtils as logging} from 'google-gax'; const version = getJSON( path.join(dirname, '..', '..', '..', '..', 'package.json') ).version; -{%- set methodNames = [] %} +{%- set methodNamesStr = "|" %} {%- for method in service.method -%} - {%- do methodNames.push(method.name.toCamelCase()) -%} + {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} {%- endfor -%} /** @@ -1113,21 +1113,21 @@ export class {{ service.name }}Client { {%- endif %} {%- endfor %} {%- if service.IAMPolicyMixin > 0 %} - {%- if 'getIamPolicy' not in methodNames %} + {%- if '|getIamPolicy|' not in methodNamesStr %} {{ iam.getIamPolicy()}} {%- endif %} - {%- if 'setIamPolicy' not in methodNames %} + {%- if '|setIamPolicy|' not in methodNamesStr %} {{ iam.setIamPolicy()}} {%- endif %} - {%- if 'testIamPermissions' not in methodNames %} + {%- if '|testIamPermissions|' not in methodNamesStr %} {{ iam.testIamPermissions()}} {%- endif %} {% endif -%} {%- if service.LocationMixin > 0 %} - {%- if 'getLocation' not in methodNames %} + {%- if '|getLocation|' not in methodNamesStr %} {{ location.getLocation() }} {%- endif %} - {%- if 'listLocations' not in methodNames %} + {%- if '|listLocations|' not in methodNamesStr %} {{ location.listLocationsAsync() }} {%- endif %} {% endif -%} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk index 9ead618d8..443dd2537 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk @@ -20,9 +20,9 @@ limitations under the License. {{license.license(commonParameters.copyrightYear)}} {% import "../../_namer.njk" as namer -%} {{- namer.initialize(id, service) -}} -{%- set methodNames = [] %} +{%- set methodNamesStr = "|" %} {%- for method in service.method -%} - {%- do methodNames.push(method.name.toCamelCase()) -%} + {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} {%- endfor -%} // @ts-ignore import * as protos from '../../protos/protos.js'; @@ -1099,7 +1099,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { {%- if (service.IAMPolicyMixin) > 0 %} {%- set IAMmethods = ['getIamPolicy', 'setIamPolicy', 'testIamPermissions'] %} {%- for method in IAMmethods %} - {%- if method not in methodNames %} + {%- if ("|" + method + "|") not in methodNamesStr %} describe('{{ method }}', () => { it('invokes {{ method }} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client( @@ -1220,7 +1220,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { {%- endif %} {%- if service.LocationMixin > 0 %} {%- set method = 'getLocation' %} - {%- if method not in methodNames %} + {%- if ("|" + method + "|") not in methodNamesStr %} describe('{{ method }}', () => { it('invokes {{ method }} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client( @@ -1329,7 +1329,7 @@ describe('{{ api.naming.version }}.{{ service.name }}Client', () => { }); {%- endif %} {%- set method = 'listLocations' %} - {%- if method not in methodNames %} + {%- if ("|" + method + "|") not in methodNamesStr %} describe('{{ method }}Async', () => { it('uses async iteration with {{method}} without error', async () => { const client = new {{ service.name.toLowerCase() }}Module.{{ api.naming.version }}.{{ service.name }}Client({{- util.initClientOptions(api.rest) -}}); From 537e6ff34aca46dd3fa08f4dc055161abb38273f Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 18:24:41 -0700 Subject: [PATCH 09/12] Update testing files --- .../test/gapic_$service_$version.ts.njk | 18 ++++++++++++++++-- .../esm/test/gapic_$service_$version.ts.njk | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk index a2f53e0f3..d1734c87a 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/test/gapic_$service_$version.ts.njk @@ -24,6 +24,20 @@ limitations under the License. {%- for method in service.method -%} {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} {%- endfor -%} +{%- set enableIamTest = false %} +{%- if service.IAMPolicyMixin > 0 %} + {%- if ('|getIamPolicy|' not in methodNamesStr) or ('|setIamPolicy|' not in methodNamesStr) or ('|testIamPermissions|' not in methodNamesStr) %} + {%- set enableIamTest = true %} + {%- endif %} +{%- endif %} + +{%- set enableLocationTest = false %} +{%- if service.LocationMixin > 0 %} + {%- if ('|getLocation|' not in methodNamesStr) or ('|listLocations|' not in methodNamesStr) %} + {%- set enableLocationTest = true %} + {%- endif %} +{%- endif %} + import * as protos from '../protos/protos'; import * as assert from 'assert'; import * as sinon from 'sinon'; @@ -48,8 +62,8 @@ import {protobuf {%- if service.longRunning.length > 0 or service.LongRunningOperationsMixin > 0 -%} , operationsProtos {%- endif -%} -{%- if service.IAMPolicyMixin > 0 %}, IamProtos{%- endif -%} -{%- if service.LocationMixin > 0 %}, LocationProtos{%- endif -%} +{%- if enableIamTest %}, IamProtos{%- endif -%} +{%- if enableLocationTest %}, LocationProtos{%- endif -%} } from 'google-gax'; {%- if not api.legacyProtoLoad %} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk index 443dd2537..251d95ea9 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/test/gapic_$service_$version.ts.njk @@ -24,6 +24,20 @@ limitations under the License. {%- for method in service.method -%} {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} {%- endfor -%} +{%- set enableIamTest = false %} +{%- if service.IAMPolicyMixin > 0 %} + {%- if ('|getIamPolicy|' not in methodNamesStr) or ('|setIamPolicy|' not in methodNamesStr) or ('|testIamPermissions|' not in methodNamesStr) %} + {%- set enableIamTest = true %} + {%- endif %} +{%- endif %} + +{%- set enableLocationTest = false %} +{%- if service.LocationMixin > 0 %} + {%- if ('|getLocation|' not in methodNamesStr) or ('|listLocations|' not in methodNamesStr) %} + {%- set enableLocationTest = true %} + {%- endif %} +{%- endif %} + // @ts-ignore import * as protos from '../../protos/protos.js'; import assert from 'assert'; @@ -49,8 +63,8 @@ import {protobuf {%- if service.longRunning.length > 0 or service.LongRunningOperationsMixin > 0 -%} , operationsProtos {%- endif -%} -{%- if service.IAMPolicyMixin > 0 %}, IamProtos{%- endif -%} -{%- if service.LocationMixin > 0 %}, LocationProtos{%- endif -%} +{%- if enableIamTest %}, IamProtos{%- endif -%} +{%- if enableLocationTest %}, LocationProtos{%- endif -%} } from 'google-gax'; {%- if not api.legacyProtoLoad %} import fs from 'fs'; From 64acbd0b7eefc3fd8ac638614a31235e4edf0a7e Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 20:30:33 -0700 Subject: [PATCH 10/12] Specify that mixin properties should also be skipped if the mixin methods are defined --- .../src/$version/$service_client.ts.njk | 14 +++++++----- .../esm/src/$version/$service_client.ts.njk | 22 ++++++++++--------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk index 2aa1cdb52..7e484ed12 100644 --- a/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk +++ b/generator/gapic-generator-typescript/templates/cjs/typescript_gapic/src/$version/$service_client.ts.njk @@ -34,6 +34,8 @@ limitations under the License. {%- endif %} {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} {%- endfor -%} +{%- set generateIam = service.IAMPolicyMixin > 0 and ('|getIamPolicy|' not in methodNamesStr or '|setIamPolicy|' not in methodNamesStr or '|testIamPermissions|' not in methodNamesStr) -%} +{%- set generateLocation = service.LocationMixin > 0 and ('|getLocation|' not in methodNamesStr or '|listLocations|' not in methodNamesStr) -%} import {% if (not api.legacyProtoLoad) and (autoPopulated === false) %}type {% endif %}* as gax from 'google-gax'; import type {Callback, CallOptions, Descriptors, ClientOptions {%- if service.longRunning.length > 0 or service.LongRunningOperationsMixin > 0 %}, GrpcClientOptions{%- endif -%} @@ -95,10 +97,10 @@ export class {{ service.name }}Client { }; warn: (code: string, message: string, warnType?: string) => void; innerApiCalls: {[name: string]: Function}; - {%- if service.IAMPolicyMixin > 0 %} + {%- if generateIam %} iamClient: IamClient; {%- endif %} - {%- if service.LocationMixin > 0 %} + {%- if generateLocation %} locationsClient: LocationsClient; {%- endif -%} {%- if service.pathTemplates.length > 0 %} @@ -224,11 +226,11 @@ export class {{ service.name }}Client { if (servicePath === this._servicePath) { this.auth.defaultScopes = staticMembers.{{ id.get("scopes") }}; } - {%- if service.IAMPolicyMixin > 0 %} + {%- if generateIam %} this.iamClient = new this._gaxModule.IamClient(this._gaxGrpc, opts); {% endif %} - {%- if service.LocationMixin > 0 %} + {%- if generateLocation %} this.locationsClient = new this._gaxModule.LocationsClient( this._gaxGrpc, opts @@ -1180,10 +1182,10 @@ export class {{ service.name }}Client { this._log.info('ending gRPC channel'); this._terminated = true; stub.close(); - {%- if service.IAMPolicyMixin > 0 %} + {%- if generateIam %} this.iamClient.close().catch(err => {throw err}); {%- endif %} - {%- if service.LocationMixin > 0 %} + {%- if generateLocation %} this.locationsClient.close().catch(err => {throw err}); {%- endif %} {%- if service.longRunning.length > 0 or service.LongRunningOperationsMixin > 0 %} diff --git a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk index fdc9457d9..d7aebc929 100644 --- a/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk +++ b/generator/gapic-generator-typescript/templates/esm/typescript_gapic/esm/src/$version/$service_client.ts.njk @@ -26,6 +26,12 @@ limitations under the License. {% import "../../../_operations.njk" as operations -%} {% import "../../../_namer.njk" as namer -%} {{- namer.initialize(id, service) -}} +{%- set methodNamesStr = "|" %} +{%- for method in service.method -%} + {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} +{%- endfor -%} +{%- set generateIam = service.IAMPolicyMixin > 0 and ('|getIamPolicy|' not in methodNamesStr or '|setIamPolicy|' not in methodNamesStr or '|testIamPermissions|' not in methodNamesStr) -%} +{%- set generateLocation = service.LocationMixin > 0 and ('|getLocation|' not in methodNamesStr or '|listLocations|' not in methodNamesStr) -%} import * as gax from 'google-gax'; import type {Callback, CallOptions, Descriptors, ClientOptions {%- if service.longRunning.length > 0 or service.LongRunningOperationsMixin > 0 %}, GrpcClientOptions{%- endif -%} @@ -70,10 +76,6 @@ import {loggingUtils as logging} from 'google-gax'; const version = getJSON( path.join(dirname, '..', '..', '..', '..', 'package.json') ).version; -{%- set methodNamesStr = "|" %} -{%- for method in service.method -%} - {%- set methodNamesStr = methodNamesStr + method.name.toCamelCase() + "|" -%} -{%- endfor -%} /** {{- util.printCommentsForService(service) }} @@ -103,10 +105,10 @@ export class {{ service.name }}Client { }; warn: (code: string, message: string, warnType?: string) => void; innerApiCalls: {[name: string]: Function}; - {%- if service.IAMPolicyMixin > 0 %} + {%- if generateIam %} iamClient: IamClient; {%- endif %} - {%- if service.LocationMixin > 0 %} + {%- if generateLocation %} locationsClient: LocationsClient; {%- endif -%} {%- if service.pathTemplates.length > 0 %} @@ -233,11 +235,11 @@ export class {{ service.name }}Client { if (servicePath === this._servicePath) { this.auth.defaultScopes = staticMembers.{{ id.get("scopes") }}; } - {%- if service.IAMPolicyMixin > 0 %} + {%- if generateIam %} this.iamClient = new this._gaxModule.IamClient(this._gaxGrpc, opts); {% endif %} - {%- if service.LocationMixin > 0 %} + {%- if generateLocation %} this.locationsClient = new this._gaxModule.LocationsClient( this._gaxGrpc, opts @@ -1188,10 +1190,10 @@ export class {{ service.name }}Client { this._log.info('ending gRPC channel'); this._terminated = true; stub.close(); - {%- if service.IAMPolicyMixin > 0 %} + {%- if generateIam %} this.iamClient.close().catch(err => {throw err}); {%- endif %} - {%- if service.LocationMixin > 0 %} + {%- if generateLocation %} this.locationsClient.close().catch(err => {throw err}); {%- endif %} {%- if service.longRunning.length > 0 or service.LongRunningOperationsMixin > 0 %} From 8cc84120f92a11d7c349ef7ddb7fe5ea3a587241 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 20:56:25 -0700 Subject: [PATCH 11/12] Updating assert statement --- .../gapic-generator-typescript/typescript/src/generator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/gapic-generator-typescript/typescript/src/generator.ts b/generator/gapic-generator-typescript/typescript/src/generator.ts index ac490f404..84a8e8187 100644 --- a/generator/gapic-generator-typescript/typescript/src/generator.ts +++ b/generator/gapic-generator-typescript/typescript/src/generator.ts @@ -19,7 +19,7 @@ import * as yaml from 'js-yaml'; import * as serializer from 'proto3-json-serializer'; import protobuf from 'protobufjs'; import type * as protos from '../../protos/index.js'; -import protoJson from '../../protos/protos.json' assert {type: 'json'}; +import protoJson from '../../protos/protos.json' with {type: 'json'}; import * as url from 'url'; import {API} from './schema/api.js'; import {processTemplates} from './templater.js'; From 0829f64f677d5242b4f266fba15fbdde80777930 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Wed, 11 Mar 2026 21:08:52 -0700 Subject: [PATCH 12/12] Update baselines for testing --- .../kms/src/v1/key_management_service_client.ts.baseline | 8 +++----- .../kms/test/gapic_key_management_service_v1.ts.baseline | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/generator/gapic-generator-typescript/baselines/kms/src/v1/key_management_service_client.ts.baseline b/generator/gapic-generator-typescript/baselines/kms/src/v1/key_management_service_client.ts.baseline index 5ab7909bf..a40757f7c 100644 --- a/generator/gapic-generator-typescript/baselines/kms/src/v1/key_management_service_client.ts.baseline +++ b/generator/gapic-generator-typescript/baselines/kms/src/v1/key_management_service_client.ts.baseline @@ -3179,7 +3179,7 @@ export class KeyManagementServiceClient { callSettings ) as AsyncIterable; } -/** + /** * Gets the access control policy for a resource. Returns an empty policy * if the resource exists and does not have a policy set. * @@ -3221,8 +3221,7 @@ export class KeyManagementServiceClient { ):Promise<[IamProtos.google.iam.v1.Policy]> { return this.iamClient.getIamPolicy(request, options, callback); } - -/** + /** * Returns permissions that a caller has on the specified resource. If the * resource does not exist, this will return an empty set of * permissions, not a NOT_FOUND error. @@ -3268,8 +3267,7 @@ export class KeyManagementServiceClient { ):Promise<[IamProtos.google.iam.v1.Policy]> { return this.iamClient.setIamPolicy(request, options, callback); } - -/** + /** * Returns permissions that a caller has on the specified resource. If the * resource does not exist, this will return an empty set of * permissions, not a NOT_FOUND error. diff --git a/generator/gapic-generator-typescript/baselines/kms/test/gapic_key_management_service_v1.ts.baseline b/generator/gapic-generator-typescript/baselines/kms/test/gapic_key_management_service_v1.ts.baseline index b0382f4b2..d2c2b0b15 100644 --- a/generator/gapic-generator-typescript/baselines/kms/test/gapic_key_management_service_v1.ts.baseline +++ b/generator/gapic-generator-typescript/baselines/kms/test/gapic_key_management_service_v1.ts.baseline @@ -16,6 +16,8 @@ // ** https://github.com/googleapis/gapic-generator-typescript ** // ** All changes to this file may be overwritten. ** + + import * as protos from '../protos/protos'; import * as assert from 'assert'; import * as sinon from 'sinon';