Skip to content

Commit f9fef48

Browse files
committed
Update constant(boolean) to return BooleanExpression
1 parent f07a909 commit f9fef48

File tree

2 files changed

+90
-6
lines changed

2 files changed

+90
-6
lines changed

packages/firestore/src/lite-api/expressions.ts

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,12 +2422,12 @@ export function constant(value: number): Expression;
24222422
export function constant(value: string): Expression;
24232423

24242424
/**
2425-
* Creates a `Constant` instance for a boolean value.
2425+
* Creates a `BooleanExpression` instance for a boolean value.
24262426
*
24272427
* @param value The boolean value.
24282428
* @return A new `Constant` instance.
24292429
*/
2430-
export function constant(value: boolean): Expression;
2430+
export function constant(value: boolean): BooleanExpression;
24312431

24322432
/**
24332433
* Creates a `Constant` instance for a null value.
@@ -2495,8 +2495,8 @@ export function constant(value: ProtoValue): Expression;
24952495
*/
24962496
export function constant(value: VectorValue): Expression;
24972497

2498-
export function constant(value: unknown): Expression {
2499-
return _constant(value, 'contant');
2498+
export function constant(value: unknown): Expression | BooleanExpression {
2499+
return _constant(value, 'constant');
25002500
}
25012501

25022502
/**
@@ -2508,8 +2508,12 @@ export function constant(value: unknown): Expression {
25082508
export function _constant(
25092509
value: unknown,
25102510
methodName: string | undefined
2511-
): Constant {
2512-
return new Constant(value, methodName);
2511+
): Constant | BooleanExpression {
2512+
if (typeof value === 'boolean') {
2513+
return new BooleanConstant(value, methodName);
2514+
} else {
2515+
return new Constant(value, methodName);
2516+
}
25132517
}
25142518

25152519
/**
@@ -2630,6 +2634,62 @@ export class BooleanExpression extends FunctionExpression {
26302634
not(): BooleanExpression {
26312635
return new BooleanExpression('not', [this], 'not');
26322636
}
2637+
2638+
/**
2639+
* Creates a conditional expression that evaluates to the 'then' expression
2640+
* if `this` expression evaluates to `true`,
2641+
* or evaluates to the 'else' expression if `this` expressions evaluates `false`.
2642+
*
2643+
* ```typescript
2644+
* // If 'age' is greater than 18, return "Adult"; otherwise, return "Minor".
2645+
* field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor"));
2646+
* ```
2647+
*
2648+
* @param thenExpr The expression to evaluate if the condition is true.
2649+
* @param elseExpr The expression to evaluate if the condition is false.
2650+
* @return A new {@code Expr} representing the conditional expression.
2651+
*/
2652+
conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression {
2653+
return new FunctionExpression(
2654+
'conditional',
2655+
[this, thenExpr, elseExpr],
2656+
'conditional'
2657+
);
2658+
}
2659+
}
2660+
2661+
/**
2662+
* @private
2663+
* @internal
2664+
*
2665+
* To return a BooleanExpr as a constant, we need to break the pattern that expects a BooleanExpr to be a
2666+
* "pipeline function". Instead of building on serialization logic built into BooleanExpr,
2667+
* we override methods with those of an internally kept Constant value.
2668+
*/
2669+
export class BooleanConstant extends BooleanExpression {
2670+
private readonly _internalConstant: Constant;
2671+
2672+
constructor(value: boolean, readonly _methodName?: string) {
2673+
super('', []);
2674+
2675+
this._internalConstant = new Constant(value, _methodName);
2676+
}
2677+
2678+
/**
2679+
* @private
2680+
* @internal
2681+
*/
2682+
_toProto(serializer: JsonProtoSerializer): ProtoValue {
2683+
return this._internalConstant._toProto(serializer);
2684+
}
2685+
2686+
/**
2687+
* @private
2688+
* @internal
2689+
*/
2690+
_readUserData(context: ParseContext): void {
2691+
return this._internalConstant._readUserData(context);
2692+
}
26332693
}
26342694

26352695
/**

packages/firestore/test/integration/api/pipeline.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,30 @@ apiDescribe.only('Pipelines', persistence => {
813813
}
814814
});
815815
});
816+
817+
it('supports boolean value constants as a BooleanExpression', async () => {
818+
const snapshots = await execute(
819+
firestore
820+
.pipeline()
821+
.collection(randomCol.path)
822+
.limit(1)
823+
.select(
824+
conditional(constant(true), constant('TRUE'), constant('FALSE')).as(
825+
'true'
826+
),
827+
conditional(
828+
constant(false),
829+
constant('TRUE'),
830+
constant('FALSE')
831+
).as('false')
832+
)
833+
);
834+
835+
expectResults(snapshots, {
836+
'true': 'TRUE',
837+
'false': 'FALSE'
838+
});
839+
});
816840
});
817841

818842
describe('stages', () => {

0 commit comments

Comments
 (0)