@@ -156,6 +156,17 @@ export interface SpannerOptions extends GrpcClientOptions {
156156 defaultTransactionOptions ?: Pick < RunTransactionOptions , 'isolationLevel' > ;
157157 observabilityOptions ?: ObservabilityOptions ;
158158 interceptors ?: any [ ] ;
159+ /**
160+ * The Trusted Cloud Domain (TPC) DNS of the service used to make requests.
161+ * Defaults to `googleapis.com`.
162+ * We support both camelCase and snake_case for the universe domain.
163+ * Customer may set any of these as both the options are same,
164+ * they both points to universe endpoint.
165+ * There is no preference for any of these option; however exception will be
166+ * thrown if both are set to different values.
167+ */
168+ universe_domain ?: string ;
169+ universeDomain ?: string ;
159170}
160171export interface RequestConfig {
161172 client : string ;
@@ -206,6 +217,45 @@ export type TranslateEnumKeys<
206217 [ P in keyof T ] : P extends U ? EnumKey < E > | null | undefined : T [ P ] ;
207218} ;
208219
220+ /**
221+ * Retrieves the universe domain.
222+ *
223+ * This function checks for a universe domain in the following order:
224+ * 1. The `universeDomain` property within the provided spanner options.
225+ * 2. The `universe_domain` property within the provided spanner options.
226+ * 3. The `GOOGLE_CLOUD_UNIVERSE_DOMAIN` environment variable.
227+ * 4. If none of the above properties will be set, it will fallback to `googleapis.com`.
228+ *
229+ * For consistency with the Auth client, if the `universe_domain` option or the
230+ * `GOOGLE_CLOUD_UNIVERSE_DOMAIN` env variable is used, this function will also set the
231+ * `universeDomain` property within the provided `SpannerOptions` object. This ensures the
232+ * Spanner client's universe domain aligns with the universe configured for authentication.
233+ *
234+ * @param {SpannerOptions } options - The Spanner client options.
235+ * @returns {string } The universe domain.
236+ */
237+ function getUniverseDomain ( options : SpannerOptions ) : string {
238+ const universeDomainEnvVar =
239+ typeof process === 'object' && typeof process . env === 'object'
240+ ? process . env [ 'GOOGLE_CLOUD_UNIVERSE_DOMAIN' ]
241+ : undefined ;
242+ const universeDomain =
243+ options ?. universeDomain ??
244+ options ?. universe_domain ??
245+ universeDomainEnvVar ??
246+ 'googleapis.com' ;
247+ // if the options.universe_domain/GOOGLE_CLOUD_UNIVERSE_DOMAIN env variable is set,
248+ // set its value to the Spanner `universeDomain` options
249+ // to match it with the universe from Auth Client
250+ if (
251+ ! options ?. universeDomain &&
252+ ( options ?. universe_domain || process . env . GOOGLE_CLOUD_UNIVERSE_DOMAIN )
253+ ) {
254+ options . universeDomain = universeDomain ;
255+ }
256+ return universeDomain ;
257+ }
258+
209259/**
210260 * [Cloud Spanner](https://cloud.google.com/spanner) is a highly scalable,
211261 * transactional, managed, NewSQL database service. Cloud Spanner solves the
@@ -259,6 +309,7 @@ class Spanner extends GrpcService {
259309 directedReadOptions : google . spanner . v1 . IDirectedReadOptions | null ;
260310 defaultTransactionOptions : RunTransactionOptions ;
261311 _observabilityOptions : ObservabilityOptions | undefined ;
312+ private _universeDomain : string ;
262313 readonly _nthClientId : number ;
263314
264315 /**
@@ -351,6 +402,16 @@ class Spanner extends GrpcService {
351402 } ;
352403 delete options . defaultTransactionOptions ;
353404
405+ if (
406+ options ?. universe_domain &&
407+ options ?. universeDomain &&
408+ options ?. universe_domain !== options ?. universeDomain
409+ ) {
410+ throw new Error (
411+ 'Please set either universe_domain or universeDomain, but not both.' ,
412+ ) ;
413+ }
414+
354415 const emulatorHost = Spanner . getSpannerEmulatorHost ( ) ;
355416 if (
356417 emulatorHost &&
@@ -361,12 +422,12 @@ class Spanner extends GrpcService {
361422 options . port = emulatorHost . port ;
362423 options . sslCreds = grpc . credentials . createInsecure ( ) ;
363424 }
425+
426+ const universeEndpoint = getUniverseDomain ( options ) ;
427+ const spannerUniverseEndpoint = 'spanner.' + universeEndpoint ;
364428 const config = {
365429 baseUrl :
366- options . apiEndpoint ||
367- options . servicePath ||
368- // TODO: for TPC, this needs to support universeDomain
369- 'spanner.googleapis.com' ,
430+ options . apiEndpoint || options . servicePath || spannerUniverseEndpoint ,
370431 protosDir : path . resolve ( __dirname , '../protos' ) ,
371432 protoServices : {
372433 Operations : {
@@ -399,6 +460,11 @@ class Spanner extends GrpcService {
399460 ) ;
400461 ensureInitialContextManagerSet ( ) ;
401462 this . _nthClientId = nextSpannerClientId ( ) ;
463+ this . _universeDomain = universeEndpoint ;
464+ }
465+
466+ get universeDomain ( ) {
467+ return this . _universeDomain ;
402468 }
403469
404470 /**
0 commit comments