@@ -9,6 +9,7 @@ const metadataFilterValueSchema: z.ZodType<unknown> = z.lazy(() =>
99 z . boolean ( ) ,
1010 z . array ( z . string ( ) ) ,
1111 z . array ( z . number ( ) ) ,
12+ z . array ( z . lazy ( ( ) => metadataFilterSchema ) ) ,
1213 z . record ( z . string ( ) , metadataFilterValueSchema ) , // Recursive for nested operators
1314 ] )
1415) ;
@@ -23,6 +24,8 @@ const ALLOWED_FILTER_OPERATORS = new Set([
2324 '$lte' ,
2425 '$in' ,
2526 '$nin' ,
27+ '$and' ,
28+ '$or' ,
2629] ) ;
2730
2831/** True if value is a string, number, or boolean (allowed for $eq, $gt, etc.). */
@@ -45,7 +48,17 @@ function validateMetadataFilterValue(value: unknown, path: string[]): string | n
4548 return null ;
4649 }
4750
48- if ( typeof value !== 'object' || Array . isArray ( value ) ) {
51+ if ( Array . isArray ( value ) ) {
52+ for ( let i = 0 ; i < value . length ; i ++ ) {
53+ const parsed = metadataFilterSchema . safeParse ( value [ i ] ) ;
54+ if ( ! parsed . success ) {
55+ return `Operator "${ path [ path . length - 1 ] } " at "${ path . join ( '.' ) } " must use an array of filter objects.` ;
56+ }
57+ }
58+ return null ;
59+ }
60+
61+ if ( typeof value !== 'object' ) {
4962 return `Unsupported filter value at "${ path . join ( '.' ) } ".` ;
5063 }
5164
@@ -70,6 +83,9 @@ function validateMetadataFilterValue(value: unknown, path: string[]): string | n
7083 ) {
7184 return `Operator "${ key } " at "${ path . join ( '.' ) } " must use a primitive value.` ;
7285 }
86+ if ( ( key === '$and' || key === '$or' ) && ! Array . isArray ( nestedValue ) ) {
87+ return `Operator "${ key } " at "${ path . join ( '.' ) } " must use an array of filter objects.` ;
88+ }
7389
7490 const nestedError = validateMetadataFilterValue ( nestedValue , [ ...path , key ] ) ;
7591 if ( nestedError ) {
0 commit comments