@@ -51,6 +51,7 @@ export type CloudFunctionClientOptions = {
51
51
52
52
export type PollOperationOptions = {
53
53
onPoll ?: OnFunction ;
54
+ onDebug ?: OnDebugFunction ;
54
55
} ;
55
56
56
57
export type Operation = {
@@ -193,24 +194,29 @@ export type CloudFunction = {
193
194
194
195
export type CreateOptions = {
195
196
onPoll ?: OnFunction ;
197
+ onDebug ?: OnDebugFunction ;
196
198
} ;
197
199
198
200
export type DeleteOptions = {
199
201
onPoll ?: OnFunction ;
202
+ onDebug ?: OnDebugFunction ;
200
203
} ;
201
204
202
205
export type PatchOptions = {
203
206
onPoll ?: OnFunction ;
207
+ onDebug ?: OnDebugFunction ;
204
208
} ;
205
209
206
210
export type DeployOptions = {
207
211
onPoll ?: OnFunction ;
208
212
onZip ?: OnZipFunction ;
209
213
onNew ?: OnFunction ;
210
214
onExisting ?: OnFunction ;
215
+ onDebug ?: OnDebugFunction ;
211
216
} & ZipOptions ;
212
217
213
218
export type OnFunction = ( ) => void ;
219
+ export type OnDebugFunction = ( f : ( ) => string ) => void ;
214
220
export type OnZipFunction = ( sourceDir : string , zipPath : string ) => void ;
215
221
216
222
export class CloudFunctionsClient {
@@ -332,6 +338,11 @@ export class CloudFunctionsClient {
332
338
async create ( cf : CloudFunction , opts ?: CreateOptions ) : Promise < CloudFunctionResponse > {
333
339
const resourceName = this . fullResourceName ( cf . name ) ;
334
340
cf . name = resourceName ;
341
+ if ( opts ?. onDebug ) {
342
+ opts . onDebug ( ( ) : string => {
343
+ return `create: computed Cloud Function:\n${ JSON . stringify ( cf , null , 2 ) } ` ;
344
+ } ) ;
345
+ }
335
346
336
347
const parent = this . parentFromName ( resourceName ) ;
337
348
const functionName = resourceName . split ( '/' ) . at ( - 1 ) ;
@@ -342,6 +353,7 @@ export class CloudFunctionsClient {
342
353
const resp : Operation = await this . #request( 'POST' , u , body ) ;
343
354
const op = await this . #pollOperation( resp . name , {
344
355
onPoll : opts ?. onPoll ,
356
+ onDebug : opts ?. onDebug ,
345
357
} ) ;
346
358
347
359
if ( ! op . response ) {
@@ -361,6 +373,7 @@ export class CloudFunctionsClient {
361
373
const resp : Operation = await this . #request( 'DELETE' , u ) ;
362
374
return await this . #pollOperation( resp . name , {
363
375
onPoll : opts ?. onPoll ,
376
+ onDebug : opts ?. onDebug ,
364
377
} ) ;
365
378
}
366
379
@@ -421,12 +434,25 @@ export class CloudFunctionsClient {
421
434
async patch ( cf : CloudFunction , opts ?: PatchOptions ) : Promise < CloudFunctionResponse > {
422
435
const resourceName = this . fullResourceName ( cf . name ) ;
423
436
cf . name = resourceName ;
437
+ if ( opts ?. onDebug ) {
438
+ opts . onDebug ( ( ) : string => {
439
+ return `patch: computed Cloud Function:\n${ JSON . stringify ( cf , null , 2 ) } ` ;
440
+ } ) ;
441
+ }
424
442
425
- const u = `${ this . #endpoints. cloudfunctions } /${ resourceName } ` ;
443
+ const updateMask = this . computeUpdateMask ( cf ) ;
444
+ if ( opts ?. onDebug ) {
445
+ opts . onDebug ( ( ) : string => {
446
+ return `Computed updateMask: ${ updateMask } ` ;
447
+ } ) ;
448
+ }
449
+
450
+ const u = `${ this . #endpoints. cloudfunctions } /${ resourceName } ?updateMask=${ updateMask } ` ;
426
451
const body = JSON . stringify ( cf ) ;
427
452
const resp : Operation = await this . #request( 'PATCH' , u , body ) ;
428
453
const op = await this . #pollOperation( resp . name , {
429
454
onPoll : opts ?. onPoll ,
455
+ onDebug : opts ?. onDebug ,
430
456
} ) ;
431
457
432
458
if ( ! op . response ) {
@@ -489,12 +515,14 @@ export class CloudFunctionsClient {
489
515
if ( opts ?. onExisting ) opts . onExisting ( ) ;
490
516
const resp : CloudFunctionResponse = await this . patch ( cf , {
491
517
onPoll : opts ?. onPoll ,
518
+ onDebug : opts ?. onDebug ,
492
519
} ) ;
493
520
return resp ;
494
521
} else {
495
522
if ( opts ?. onNew ) opts . onNew ( ) ;
496
523
const resp : CloudFunctionResponse = await this . create ( cf , {
497
524
onPoll : opts ?. onPoll ,
525
+ onDebug : opts ?. onDebug ,
498
526
} ) ;
499
527
return resp ;
500
528
}
@@ -571,4 +599,27 @@ export class CloudFunctionsClient {
571
599
const parent = parts . slice ( 0 , parts . length - 2 ) . join ( '/' ) ;
572
600
return parent ;
573
601
}
602
+
603
+ computeUpdateMask ( cf : CloudFunction ) : string {
604
+ const keys : string [ ] = [ ] ;
605
+
606
+ const iter = ( obj : Object , root ?: string ) => {
607
+ for ( const [ k , v ] of Object . entries ( obj ) ) {
608
+ if ( v === undefined ) {
609
+ continue ;
610
+ }
611
+
612
+ const pth = root ? root + '.' + k : k ;
613
+ if ( typeof v === 'object' && ! Array . isArray ( v ) ) {
614
+ iter ( v , pth ) ;
615
+ } else {
616
+ keys . push ( pth ) ;
617
+ }
618
+ }
619
+ } ;
620
+
621
+ iter ( cf ) ;
622
+
623
+ return keys . join ( ',' ) ;
624
+ }
574
625
}
0 commit comments