@@ -460,11 +460,11 @@ function coalesceSearchable(
460460 global : string [ ] | null | undefined ,
461461) : string [ ] | null | undefined {
462462 if ( entity !== undefined ) {
463- if ( entity === null ) return [ ]
463+ if ( entity === null ) return null
464464 if ( global === null || global === undefined ) return entity
465465 return unionStrings ( global , entity )
466466 }
467- if ( global === null ) return [ ]
467+ if ( global === null ) return null
468468 return global
469469}
470470
@@ -615,8 +615,15 @@ export function opsAreClosed(field: EffectiveFilterField, caps: EffectiveQueryCa
615615export function fieldAllows ( field : EffectiveFilterField , op : FilterOp , caps : EffectiveQueryCapabilities ) : boolean {
616616 const ops = opsForField ( field , caps )
617617 if ( ops . includes ( op ) ) return true
618- for ( const [ alias , target ] of Object . entries ( caps . aliases ) ) {
619- if ( target === op && isFilterOp ( alias ) && ops . includes ( alias ) ) return true
618+ const names = Object . keys ( caps . aliases )
619+ let i = 0
620+ while ( i < names . length ) {
621+ const alias = names [ i ] as string
622+ i += 1
623+ const target = caps . aliases [ alias as FilterOp ]
624+ if ( target !== op ) continue
625+ if ( ! isFilterOp ( alias ) ) continue
626+ if ( ops . includes ( alias ) ) return true
620627 }
621628 return false
622629}
@@ -676,7 +683,6 @@ export function applyHarvest(
676683 extra . map ( ( field ) => {
677684 const row : EffectiveFilterField = { field : field . field }
678685 if ( field . type !== undefined ) row . type = field . type
679- if ( field . ops !== undefined ) row . ops = field . ops
680686 return row
681687 } ) ,
682688 ) ,
@@ -759,10 +765,9 @@ export function readJsonPathList(body: unknown, path: string): unknown[] {
759765
760766function applyJsonPathFilter ( node : unknown , token : string ) : unknown [ ] | undefined {
761767 const match = / ^ \? \( @ \. ( [ A - Z a - z _ ] [ \w ] * ) = = ( t r u e | f a l s e | n u l l | " [ ^ " ] * " | ' [ ^ ' ] * ' | [ ^ \s ) ] + ) \) $ / . exec ( token )
762- if ( match === null || ! Array . isArray ( node ) ) return undefined
768+ if ( match === null || match [ 1 ] === undefined || match [ 2 ] === undefined || ! Array . isArray ( node ) ) return undefined
763769 const key = match [ 1 ]
764- const expected = parseJsonPathLiteral ( match [ 2 ] ?? "" )
765- if ( key === undefined ) return undefined
770+ const expected = parseJsonPathLiteral ( match [ 2 ] )
766771 return node . filter ( ( item ) => {
767772 if ( item === null || typeof item !== "object" ) return false
768773 return ( item as Record < string , unknown > ) [ key ] === expected
@@ -782,14 +787,28 @@ function parseJsonPathLiteral(raw: string): unknown {
782787
783788function tokenizeJsonPath ( path : string ) : string [ ] {
784789 const out : string [ ] = [ ]
785- for ( const part of path . split ( "." ) ) {
786- const match = / ^ ( [ ^ [ ] * ) (?: \[ ( \* | \d + | \? \( [ ^ ) ] + \) ) \] ) ? $ / . exec ( part )
787- if ( match === null ) {
788- out . push ( part )
790+ let buf = ""
791+ for ( let i = 0 ; i < path . length ; i ++ ) {
792+ const ch = path [ i ]
793+ if ( ch === "." ) {
794+ if ( buf !== "" ) out . push ( buf )
795+ buf = ""
789796 continue
790797 }
791- if ( match [ 1 ] !== undefined && match [ 1 ] !== "" ) out . push ( match [ 1 ] )
792- if ( match [ 2 ] !== undefined ) out . push ( match [ 2 ] )
798+ if ( ch === "[" ) {
799+ if ( buf !== "" ) out . push ( buf )
800+ buf = ""
801+ const end = path . indexOf ( "]" , i )
802+ if ( end === - 1 ) {
803+ out . push ( path . slice ( i ) )
804+ return out
805+ }
806+ out . push ( path . slice ( i + 1 , end ) )
807+ i = end
808+ continue
809+ }
810+ buf += ch
793811 }
812+ if ( buf !== "" ) out . push ( buf )
794813 return out
795814}
0 commit comments