@@ -31,10 +31,12 @@ import type { ClientOptions, RetryConfig, ServerInfo } from "./types.js";
3131import { ConfigWatcher } from "./watcher.js" ;
3232
3333/**
34- * Options for get() with nullable support.
34+ * Options for get() with nullable and per-call timeout support.
3535 */
3636interface GetOptions {
3737 readonly nullable ?: boolean ;
38+ /** Per-call timeout in ms. Overrides the client default. */
39+ readonly timeout ?: number ;
3840}
3941
4042/**
@@ -122,9 +124,24 @@ export class ConfigClient {
122124 /**
123125 * Get a config value converted to the specified type.
124126 */
125- get ( tenantId : string , fieldPath : string , type : typeof Number ) : Promise < number > ;
126- get ( tenantId : string , fieldPath : string , type : typeof Boolean ) : Promise < boolean > ;
127- get ( tenantId : string , fieldPath : string , type : typeof String ) : Promise < string > ;
127+ get (
128+ tenantId : string ,
129+ fieldPath : string ,
130+ type : typeof Number ,
131+ options ?: { timeout ?: number } ,
132+ ) : Promise < number > ;
133+ get (
134+ tenantId : string ,
135+ fieldPath : string ,
136+ type : typeof Boolean ,
137+ options ?: { timeout ?: number } ,
138+ ) : Promise < boolean > ;
139+ get (
140+ tenantId : string ,
141+ fieldPath : string ,
142+ type : typeof String ,
143+ options ?: { timeout ?: number } ,
144+ ) : Promise < string > ;
128145 /**
129146 * Get a config value with nullable support.
130147 * Returns null if the field has no value instead of throwing.
@@ -133,19 +150,19 @@ export class ConfigClient {
133150 tenantId : string ,
134151 fieldPath : string ,
135152 type : typeof Number ,
136- options : { nullable : true } ,
153+ options : { nullable : true ; timeout ?: number } ,
137154 ) : Promise < number | null > ;
138155 get (
139156 tenantId : string ,
140157 fieldPath : string ,
141158 type : typeof Boolean ,
142- options : { nullable : true } ,
159+ options : { nullable : true ; timeout ?: number } ,
143160 ) : Promise < boolean | null > ;
144161 get (
145162 tenantId : string ,
146163 fieldPath : string ,
147164 type : typeof String ,
148- options : { nullable : true } ,
165+ options : { nullable : true ; timeout ?: number } ,
149166 ) : Promise < string | null > ;
150167 get (
151168 tenantId : string ,
@@ -157,11 +174,10 @@ export class ConfigClient {
157174 const nullable = options ?. nullable ?? false ;
158175
159176 const fn = async ( ) => {
160- const resp = await this . callGetField ( {
161- tenantId,
162- fieldPath,
163- includeDescription : false ,
164- } ) ;
177+ const resp = await this . callGetField (
178+ { tenantId, fieldPath, includeDescription : false } ,
179+ options ?. timeout ,
180+ ) ;
165181
166182 const cv = resp . value ;
167183 if ( cv === undefined || cv . value === undefined ) {
@@ -189,12 +205,12 @@ export class ConfigClient {
189205 *
190206 * @returns A record mapping field paths to their string values.
191207 */
192- async getAll ( tenantId : string ) : Promise < Record < string , string > > {
208+ async getAll ( tenantId : string , options ?: { timeout ?: number } ) : Promise < Record < string , string > > {
193209 const fn = async ( ) => {
194- const resp = await this . callGetConfig ( {
195- tenantId,
196- includeDescriptions : false ,
197- } ) ;
210+ const resp = await this . callGetConfig (
211+ { tenantId, includeDescriptions : false } ,
212+ options ?. timeout ,
213+ ) ;
198214
199215 const result : Record < string , string > = { } ;
200216 if ( resp . config ) {
@@ -212,13 +228,17 @@ export class ConfigClient {
212228 * Set a config value. The value is sent as a string -- the server
213229 * coerces it to the schema-defined type.
214230 */
215- async set ( tenantId : string , fieldPath : string , value : string ) : Promise < void > {
231+ async set (
232+ tenantId : string ,
233+ fieldPath : string ,
234+ value : string ,
235+ options ?: { timeout ?: number } ,
236+ ) : Promise < void > {
216237 const fn = async ( ) => {
217- await this . callSetField ( {
218- tenantId,
219- fieldPath,
220- value : { stringValue : value } ,
221- } ) ;
238+ await this . callSetField (
239+ { tenantId, fieldPath, value : { stringValue : value } } ,
240+ options ?. timeout ,
241+ ) ;
222242 } ;
223243
224244 return this . withRetryAndMap ( fn ) ;
@@ -233,18 +253,17 @@ export class ConfigClient {
233253 async setMany (
234254 tenantId : string ,
235255 values : Record < string , string > ,
236- options ?: { description ?: string } ,
256+ options ?: { description ?: string ; timeout ?: number } ,
237257 ) : Promise < void > {
238258 const fn = async ( ) => {
239259 const updates = Object . entries ( values ) . map ( ( [ fieldPath , v ] ) => ( {
240260 fieldPath,
241261 value : { stringValue : v } ,
242262 } ) ) ;
243- await this . callSetFields ( {
244- tenantId,
245- updates,
246- description : options ?. description ,
247- } ) ;
263+ await this . callSetFields (
264+ { tenantId, updates, description : options ?. description } ,
265+ options ?. timeout ,
266+ ) ;
248267 } ;
249268
250269 return this . withRetryAndMap ( fn ) ;
@@ -253,13 +272,13 @@ export class ConfigClient {
253272 /**
254273 * Set a config field to null.
255274 */
256- async setNull ( tenantId : string , fieldPath : string ) : Promise < void > {
275+ async setNull (
276+ tenantId : string ,
277+ fieldPath : string ,
278+ options ?: { timeout ?: number } ,
279+ ) : Promise < void > {
257280 const fn = async ( ) => {
258- await this . callSetField ( {
259- tenantId,
260- fieldPath,
261- value : undefined ,
262- } ) ;
281+ await this . callSetField ( { tenantId, fieldPath, value : undefined } , options ?. timeout ) ;
263282 } ;
264283
265284 return this . withRetryAndMap ( fn ) ;
@@ -321,12 +340,12 @@ export class ConfigClient {
321340 }
322341 }
323342
324- private callGetField ( request : GetFieldRequest ) : Promise < GetFieldResponse > {
343+ private callGetField ( request : GetFieldRequest , timeoutMs ?: number ) : Promise < GetFieldResponse > {
325344 return new Promise ( ( resolve , reject ) => {
326345 this . configStub . getField (
327346 request ,
328347 this . metadata ,
329- { deadline : Date . now ( ) + this . timeout } ,
348+ { deadline : Date . now ( ) + ( timeoutMs ?? this . timeout ) } ,
330349 ( err : ServiceError | null , resp : GetFieldResponse ) => {
331350 if ( err ) reject ( err ) ;
332351 else resolve ( resp ) ;
@@ -335,12 +354,12 @@ export class ConfigClient {
335354 } ) ;
336355 }
337356
338- private callGetConfig ( request : GetConfigRequest ) : Promise < GetConfigResponse > {
357+ private callGetConfig ( request : GetConfigRequest , timeoutMs ?: number ) : Promise < GetConfigResponse > {
339358 return new Promise ( ( resolve , reject ) => {
340359 this . configStub . getConfig (
341360 request ,
342361 this . metadata ,
343- { deadline : Date . now ( ) + this . timeout } ,
362+ { deadline : Date . now ( ) + ( timeoutMs ?? this . timeout ) } ,
344363 ( err : ServiceError | null , resp : GetConfigResponse ) => {
345364 if ( err ) reject ( err ) ;
346365 else resolve ( resp ) ;
@@ -349,12 +368,12 @@ export class ConfigClient {
349368 } ) ;
350369 }
351370
352- private callSetField ( request : SetFieldRequest ) : Promise < SetFieldResponse > {
371+ private callSetField ( request : SetFieldRequest , timeoutMs ?: number ) : Promise < SetFieldResponse > {
353372 return new Promise ( ( resolve , reject ) => {
354373 this . configStub . setField (
355374 request ,
356375 this . metadata ,
357- { deadline : Date . now ( ) + this . timeout } ,
376+ { deadline : Date . now ( ) + ( timeoutMs ?? this . timeout ) } ,
358377 ( err : ServiceError | null , resp : SetFieldResponse ) => {
359378 if ( err ) reject ( err ) ;
360379 else resolve ( resp ) ;
@@ -363,12 +382,12 @@ export class ConfigClient {
363382 } ) ;
364383 }
365384
366- private callSetFields ( request : SetFieldsRequest ) : Promise < SetFieldsResponse > {
385+ private callSetFields ( request : SetFieldsRequest , timeoutMs ?: number ) : Promise < SetFieldsResponse > {
367386 return new Promise ( ( resolve , reject ) => {
368387 this . configStub . setFields (
369388 request ,
370389 this . metadata ,
371- { deadline : Date . now ( ) + this . timeout } ,
390+ { deadline : Date . now ( ) + ( timeoutMs ?? this . timeout ) } ,
372391 ( err : ServiceError | null , resp : SetFieldsResponse ) => {
373392 if ( err ) reject ( err ) ;
374393 else resolve ( resp ) ;
0 commit comments