@@ -223,15 +223,28 @@ export class ExpressionWriter {
223
223
}
224
224
225
225
private writeCollectionPredicate ( expr : BinaryExpr , operator : string ) {
226
- this . block ( ( ) => {
227
- this . writeFieldCondition (
228
- expr . left ,
229
- ( ) => {
230
- this . write ( expr . right ) ;
231
- } ,
232
- operator === '?' ? 'some' : operator === '!' ? 'every' : 'none'
233
- ) ;
234
- } ) ;
226
+ // check if the operand should be compiled to a relation query
227
+ // or a plain expression
228
+ const compileToRelationQuery =
229
+ ( this . isPostGuard && this . isFutureMemberAccess ( expr . left ) ) ||
230
+ ( ! this . isPostGuard && ! this . isFutureMemberAccess ( expr . left ) ) ;
231
+
232
+ if ( compileToRelationQuery ) {
233
+ this . block ( ( ) => {
234
+ this . writeFieldCondition (
235
+ expr . left ,
236
+ ( ) => {
237
+ // inner scope of collection expression is always compiled as non-post-guard
238
+ const innerWriter = new ExpressionWriter ( this . writer , false ) ;
239
+ innerWriter . write ( expr . right ) ;
240
+ } ,
241
+ operator === '?' ? 'some' : operator === '!' ? 'every' : 'none'
242
+ ) ;
243
+ } ) ;
244
+ } else {
245
+ const plain = this . plainExprBuilder . transform ( expr ) ;
246
+ this . writer . write ( `${ plain } ? ${ TRUE } : ${ FALSE } ` ) ;
247
+ }
235
248
}
236
249
237
250
private isFieldAccess ( expr : Expression ) : boolean {
@@ -275,6 +288,19 @@ export class ExpressionWriter {
275
288
}
276
289
}
277
290
291
+ private writeIdFieldsCheck ( model : DataModel , value : Expression ) {
292
+ const idFields = this . requireIdFields ( model ) ;
293
+ idFields . forEach ( ( idField , idx ) => {
294
+ // eg: id: user.id
295
+ this . writer . write ( `${ idField . name } :` ) ;
296
+ this . plain ( value ) ;
297
+ this . writer . write ( `.${ idField . name } ` ) ;
298
+ if ( idx !== idFields . length - 1 ) {
299
+ this . writer . write ( ',' ) ;
300
+ }
301
+ } ) ;
302
+ }
303
+
278
304
private writeComparison ( expr : BinaryExpr , operator : ComparisonOperator ) {
279
305
const leftIsFieldAccess = this . isFieldAccess ( expr . left ) ;
280
306
const rightIsFieldAccess = this . isFieldAccess ( expr . right ) ;
@@ -298,7 +324,7 @@ export class ExpressionWriter {
298
324
operator = this . negateOperator ( operator ) ;
299
325
}
300
326
301
- if ( isMemberAccessExpr ( fieldAccess ) && isFutureExpr ( fieldAccess . operand ) ) {
327
+ if ( this . isFutureMemberAccess ( fieldAccess ) ) {
302
328
// future().field should be treated as the "field" directly, so we
303
329
// strip 'future().' and synthesize a reference expr
304
330
fieldAccess = {
@@ -338,8 +364,6 @@ export class ExpressionWriter {
338
364
// right now this branch only serves comparison with `auth`, like
339
365
// @@allow ('all', owner == auth())
340
366
341
- const idFields = this . requireIdFields ( dataModel ) ;
342
-
343
367
if ( operator !== '==' && operator !== '!=' ) {
344
368
throw new PluginError ( name , 'Only == and != operators are allowed' ) ;
345
369
}
@@ -354,25 +378,13 @@ export class ExpressionWriter {
354
378
}
355
379
356
380
this . block ( ( ) => {
357
- idFields . forEach ( ( idField , idx ) => {
358
- const writeIdsCheck = ( ) => {
359
- // id: user.id
360
- this . writer . write ( `${ idField . name } :` ) ;
361
- this . plain ( operand ) ;
362
- this . writer . write ( `.${ idField . name } ` ) ;
363
- if ( idx !== idFields . length - 1 ) {
364
- this . writer . write ( ',' ) ;
365
- }
366
- } ;
367
-
368
- if ( isThisExpr ( fieldAccess ) && operator === '!=' ) {
369
- // wrap a not
370
- this . writer . writeLine ( 'NOT:' ) ;
371
- this . block ( ( ) => writeIdsCheck ( ) ) ;
372
- } else {
373
- writeIdsCheck ( ) ;
374
- }
375
- } ) ;
381
+ if ( isThisExpr ( fieldAccess ) && operator === '!=' ) {
382
+ // negate
383
+ this . writer . writeLine ( 'isNot:' ) ;
384
+ this . block ( ( ) => this . writeIdFieldsCheck ( dataModel , operand ) ) ;
385
+ } else {
386
+ this . writeIdFieldsCheck ( dataModel , operand ) ;
387
+ }
376
388
} ) ;
377
389
} else {
378
390
if ( this . equivalentRefs ( fieldAccess , operand ) ) {
@@ -386,7 +398,13 @@ export class ExpressionWriter {
386
398
// we should generate a field reference (comparing fields in the same model)
387
399
this . writeFieldReference ( operand ) ;
388
400
} else {
389
- this . plain ( operand ) ;
401
+ if ( dataModel && this . isModelTyped ( operand ) ) {
402
+ // the comparison is between model types, generate id fields comparison block
403
+ this . block ( ( ) => this . writeIdFieldsCheck ( dataModel , operand ) ) ;
404
+ } else {
405
+ // scalar value, just generate the plain expression
406
+ this . plain ( operand ) ;
407
+ }
390
408
}
391
409
} ) ;
392
410
}
@@ -400,6 +418,10 @@ export class ExpressionWriter {
400
418
) ;
401
419
}
402
420
421
+ private isFutureMemberAccess ( expr : Expression ) : expr is MemberAccessExpr {
422
+ return isMemberAccessExpr ( expr ) && isFutureExpr ( expr . operand ) ;
423
+ }
424
+
403
425
private requireIdFields ( dataModel : DataModel ) {
404
426
const idFields = getIdFields ( dataModel ) ;
405
427
if ( ! idFields || idFields . length === 0 ) {
0 commit comments