@@ -456,54 +456,7 @@ export class DataConnectApiClient {
456456 return { capitalized, camelCase } ;
457457 }
458458
459- /**
460- * Extracts property keys from an object or array of objects as a space-separated string,
461- * including recursively nested object/array fields for the `@allow(fields: ...)` directive.
462- * Leverages a hierarchical tree to deduplicate and merge fields.
463- */
464- private getFieldsString ( data : unknown ) : string {
465- const root : FieldNode = { children : new Map ( ) } ;
466- this . mergeFieldsIntoTree ( data , root ) ;
467- return this . serializeFieldNode ( root ) ;
468- }
469459
470- private mergeFieldsIntoTree ( data : unknown , node : FieldNode ) : void {
471- if ( validator . isArray ( data ) ) {
472- for ( const item of data ) {
473- this . mergeFieldsIntoTree ( item , node ) ;
474- }
475- } else if ( validator . isNonNullObject ( data ) && ! ( data instanceof Date ) ) {
476- const record = data as Record < string , unknown > ;
477- for ( const [ key , val ] of Object . entries ( record ) ) {
478- if ( val === undefined ) {
479- continue ;
480- }
481- let childNode = node . children . get ( key ) ;
482- if ( ! childNode ) {
483- childNode = { children : new Map ( ) } ;
484- node . children . set ( key , childNode ) ;
485- }
486- if ( key . includes ( '_on_' ) ) {
487- this . mergeFieldsIntoTree ( val , childNode ) ;
488- }
489- }
490- }
491- }
492-
493- private serializeFieldNode ( node : FieldNode ) : string {
494- const parts : string [ ] = [ ] ;
495- const sortedKeys = Array . from ( node . children . keys ( ) ) . sort ( ( a , b ) => a . localeCompare ( b ) ) ;
496- for ( const key of sortedKeys ) {
497- const childNode = node . children . get ( key ) ! ;
498- if ( childNode . children . size > 0 ) {
499- const nestedString = this . serializeFieldNode ( childNode ) ;
500- parts . push ( `${ key } { ${ nestedString } }` ) ;
501- } else {
502- parts . push ( key ) ;
503- }
504- }
505- return parts . join ( ' ' ) ;
506- }
507460
508461 private handleBulkImportErrors ( err : FirebaseDataConnectError ) : never {
509462 if ( err . code === `data-connect/${ DATA_CONNECT_ERROR_CODE_MAPPING . QUERY_ERROR } ` ) {
@@ -584,7 +537,7 @@ export class DataConnectApiClient {
584537
585538 try {
586539 const { capitalized, camelCase } = this . getTableNames ( tableName ) ;
587- const keys = this . getFieldsString ( data ) ;
540+ const keys = getFieldsString ( data ) ;
588541 const mutation =
589542 `mutation($data: ${ capitalized } _Data! @allow(fields: "${ keys } ")) {
590543 ${ camelCase } _${ operationType } (data: $data)
@@ -627,7 +580,7 @@ export class DataConnectApiClient {
627580
628581 try {
629582 const { capitalized, camelCase } = this . getTableNames ( tableName ) ;
630- const keys = this . getFieldsString ( data ) ;
583+ const keys = getFieldsString ( data ) ;
631584 const mutation =
632585 `mutation($data: [${ capitalized } _Data!]! @allow(fields: "${ keys } ", maxCount: ${ ALLOW_DIRECTIVE_MAX_COUNT } )) {
633586 ${ camelCase } _${ operationType } (data: $data)
@@ -678,3 +631,55 @@ interface ServerError {
678631 message ?: string ;
679632 status ?: string ;
680633}
634+
635+ /**
636+ * Extracts property keys from an object or array of objects as a space-separated string,
637+ * including recursively nested object/array fields for the `@allow(fields: ...)` directive.
638+ * Leverages a hierarchical tree to deduplicate and merge fields.
639+ *
640+ * @internal
641+ */
642+ export function getFieldsString ( data : unknown ) : string {
643+ const root : FieldNode = { children : new Map ( ) } ;
644+ mergeFieldsIntoTree ( data , root ) ;
645+ return serializeFieldNode ( root ) ;
646+ }
647+
648+ function mergeFieldsIntoTree ( data : unknown , node : FieldNode ) : void {
649+ if ( validator . isArray ( data ) ) {
650+ data . forEach ( ( item ) => mergeFieldsIntoTree ( item , node ) ) ;
651+ return ;
652+ }
653+ if ( ! validator . isNonNullObject ( data ) || data instanceof Date ) {
654+ return ;
655+ }
656+ const record = data as Record < string , unknown > ;
657+ for ( const [ key , val ] of Object . entries ( record ) ) {
658+ if ( val === undefined ) {
659+ continue ;
660+ }
661+ let childNode = node . children . get ( key ) ;
662+ if ( ! childNode ) {
663+ childNode = { children : new Map ( ) } ;
664+ node . children . set ( key , childNode ) ;
665+ }
666+ if ( key . includes ( '_on_' ) ) {
667+ mergeFieldsIntoTree ( val , childNode ) ;
668+ }
669+ }
670+ }
671+
672+ function serializeFieldNode ( node : FieldNode ) : string {
673+ const parts : string [ ] = [ ] ;
674+ const sortedKeys = Array . from ( node . children . keys ( ) ) . sort ( ( a , b ) => a . localeCompare ( b ) ) ;
675+ for ( const key of sortedKeys ) {
676+ const childNode = node . children . get ( key ) ! ;
677+ if ( childNode . children . size > 0 ) {
678+ const nestedString = serializeFieldNode ( childNode ) ;
679+ parts . push ( `${ key } { ${ nestedString } }` ) ;
680+ } else {
681+ parts . push ( key ) ;
682+ }
683+ }
684+ return parts . join ( ' ' ) ;
685+ }
0 commit comments