Skip to content
This repository was archived by the owner on Feb 7, 2026. It is now read-only.

Commit 0d7e16f

Browse files
authored
fix: reuse auth across clients (#1527)
* chore: fix owlbot configs, regenerate * Apply suggestions from code review * WIP - two different ways * don't overwrite handwritten methods * change to sync file read * chore: periodic regen * run postprocessor * upgrade dependencies to node 18 * Revert "upgrade dependencies to node 18" This reverts commit b7ca3fc. * periodic regeneration + update to node 18 on autogen branch * fix lint errors * more lint fixes * fix: reuse auth * update to ensure suboptions get passed to gax * lint
1 parent 30f2457 commit 0d7e16f

File tree

4 files changed

+51
-5
lines changed

4 files changed

+51
-5
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"compile-protos": "compileProtos src",
3636
"docs": "jsdoc -c .jsdoc.js",
3737
"fix": "gts fix",
38-
"gen-central-client": "tsc scripts/gen_uber_class.ts && cd scripts && node gen_uber_class.js && cd ..",
38+
"gen-central-client": "tsc scripts/gen_uber_class.ts && cd scripts && node gen_uber_class.js && rm gen_uber_class.js && cd ..",
3939
"lint": "gts check",
4040
"prelint": "cd samples; npm link ../; npm install",
4141
"prepare": "npm run compile-protos && npm run gen-central-client && npm run compile",

scripts/gen_uber_class.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ function makeImports(clients: string[]) {
250250
imports = imports.concat('} from ".";');
251251
const staticImports = `
252252
import type * as gax from "google-gax";
253-
import {Callback, CallOptions, ClientOptions, PaginationCallback} from "google-gax";
253+
import {Callback, CallOptions, ClientOptions, GoogleAuth, PaginationCallback} from "google-gax";
254254
import {Transform} from 'stream';
255255
`;
256256

@@ -334,8 +334,10 @@ function buildClientConstructor(clients: string[]) {
334334
* @param {object} [SubClientOptions] - These options will be shared across subclients.
335335
* To have sub-clients with different options, instantiate each client separately.
336336
*/`;
337-
let constructorInitializers =
338-
'\tconstructor(options?: BigQueryClientOptions, subClientOptions?: SubClientOptions){\n';
337+
let constructorInitializers = `\tconstructor(options?: BigQueryClientOptions, subClientOptions?: SubClientOptions){
338+
subClientOptions = subClientOptions || {};
339+
subClientOptions.opts = subClientOptions.opts || {};\n\n`;
340+
let clientCounter = 0;
339341
for (const client in clients) {
340342
const clientName = parseClientName(clients[client]);
341343
variableDecl = variableDecl.concat(
@@ -344,6 +346,16 @@ function buildClientConstructor(clients: string[]) {
344346
constructorInitializers = constructorInitializers.concat(
345347
`\t\tthis.${clientName} = options?.${clientName} ?? new ${clients[client]}(subClientOptions?.opts, subClientOptions?.gaxInstance);\n`,
346348
);
349+
// add statement about auth only after the first subClient
350+
if (clientCounter === 0) {
351+
constructorInitializers =
352+
constructorInitializers.concat(`\n\t\t// utilize whatever auth was created with the first client for the rest of the clients
353+
// this will either be what the user passed into subClientOptions.opts.auth, or whatever was
354+
// initialized by default in gax. We reuse this auth rather than instantiating a default ourselves
355+
// so that we do not have to keep this code in sync with gax
356+
subClientOptions.opts.auth = this.${clientName}.auth;\n\n`);
357+
clientCounter++;
358+
}
347359
}
348360
constructorInitializers = constructorInitializers.concat('\t}');
349361
let output = 'export class BigQueryClient{\n';

src/bigquery.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
Callback,
3030
CallOptions,
3131
ClientOptions,
32+
GoogleAuth,
3233
PaginationCallback,
3334
} from 'google-gax';
3435
import {Transform} from 'stream';
@@ -103,12 +104,22 @@ export class BigQueryClient {
103104
options?: BigQueryClientOptions,
104105
subClientOptions?: SubClientOptions,
105106
) {
107+
subClientOptions = subClientOptions || {};
108+
subClientOptions.opts = subClientOptions.opts || {};
109+
106110
this.datasetClient =
107111
options?.datasetClient ??
108112
new DatasetServiceClient(
109113
subClientOptions?.opts,
110114
subClientOptions?.gaxInstance,
111115
);
116+
117+
// utilize whatever auth was created with the first client for the rest of the clients
118+
// this will either be what the user passed into subClientOptions.opts.auth, or whatever was
119+
// initialized by default in gax. We reuse this auth rather than instantiating a default ourselves
120+
// so that we do not have to keep this code in sync with gax
121+
subClientOptions.opts.auth = this.datasetClient.auth;
122+
112123
this.tableClient =
113124
options?.tableClient ??
114125
new TableServiceClient(

test/bigquery_test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
JobServiceClient,
3535
RoutineServiceClient,
3636
} from '../src';
37+
import {GoogleAuth} from 'google-gax';
3738

3839
// this test assumes that the npm "pretest" session has been run
3940
// and the client was regenerated immediately before these tests are run
@@ -68,7 +69,7 @@ describe('BigQueryClient handwritten methods work as expected', () => {
6869

6970
describe('BigQueryClient autogenerated methods work as expected', () => {
7071
describe('BigQueryClient should be able to handle passing in clients and options', () => {
71-
const subOptions: SubClientOptions = {
72+
let subOptions: SubClientOptions = {
7273
opts: {
7374
universeDomain: 'fake-universe-domain',
7475
},
@@ -145,6 +146,28 @@ describe('BigQueryClient autogenerated methods work as expected', () => {
145146
'bigquery.fake-universe-domain',
146147
);
147148
});
149+
it('creates a central client and auth is reused across clients', () => {
150+
subOptions = {
151+
opts: {
152+
auth: new GoogleAuth({apiKey: 'fake-key'}),
153+
},
154+
};
155+
156+
const client = new BigQueryClient({}, subOptions);
157+
assert.ok(client);
158+
assert.strictEqual(
159+
client.datasetClient.auth.apiKey,
160+
'fake-key', // would be null if auth was initialized by default
161+
);
162+
assert.deepStrictEqual(client.tableClient.auth.apiKey, 'fake-key');
163+
assert.deepStrictEqual(client.jobClient.auth.apiKey, 'fake-key');
164+
assert.deepStrictEqual(client.routineClient.auth.apiKey, 'fake-key');
165+
assert.deepStrictEqual(client.modelClient.auth.apiKey, 'fake-key');
166+
assert.deepStrictEqual(
167+
client.rowAccessPolicyClient.auth.apiKey,
168+
'fake-key',
169+
);
170+
});
148171
});
149172

150173
// It is not important that these unit tests validate the responses

0 commit comments

Comments
 (0)