Skip to content

Commit d881c5f

Browse files
feat(firestore): variable TS implementation
1 parent 42b3c05 commit d881c5f

4 files changed

Lines changed: 50 additions & 4 deletions

File tree

packages/firestore/lib/pipelines/expressions.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import type { Bytes } from '../modular/Bytes';
2626
export type ExpressionType =
2727
| 'Field'
2828
| 'Constant'
29+
| 'Variable'
2930
| 'Function'
3031
| 'AggregateFunction'
3132
| 'ListOfExpressions'
@@ -148,11 +149,25 @@ export interface ConstantExpression extends FluentExpressionMethods {
148149
readonly _brand?: 'ConstantExpression';
149150
}
150151

152+
/**
153+
* @beta
154+
* Variable expression returned by `variable(...)`.
155+
*/
156+
export interface VariableExpression extends Selectable, FluentExpressionMethods {
157+
readonly _brand?: 'VariableExpression';
158+
}
159+
151160
/**
152161
* @beta
153162
* Expression type for pipeline parameters (field refs, literals, function results).
154163
*/
155-
export type Expression = Field | FunctionExpression | ConstantExpression | Selectable | string;
164+
export type Expression =
165+
| Field
166+
| FunctionExpression
167+
| ConstantExpression
168+
| VariableExpression
169+
| Selectable
170+
| string;
156171

157172
/**
158173
* @beta
@@ -258,6 +273,7 @@ type BooleanExpressionNode = RuntimeExpressionNode & RuntimeExpressionMethods &
258273
type RuntimeExpressionFluentNode =
259274
| (RuntimeExpressionNode & RuntimeExpressionMethods & Field)
260275
| (RuntimeExpressionNode & RuntimeExpressionMethods & FunctionExpression)
276+
| (RuntimeExpressionNode & RuntimeExpressionMethods & VariableExpression)
261277
| BooleanExpressionNode
262278
| ConstantExpressionNode;
263279
type FieldNode = RuntimeExpressionFluentNode & Field;
@@ -550,6 +566,16 @@ function createConstant(value: unknown): ConstantExpressionNode {
550566
});
551567
}
552568

569+
function createVariable(name: unknown): RuntimeExpressionFluentNode & VariableExpression {
570+
return createNode(expressionProto, {
571+
[RUNTIME_NODE_SYMBOL]: true,
572+
__kind: 'expression',
573+
exprType: 'Variable',
574+
selectable: true,
575+
name: String(name ?? ''),
576+
});
577+
}
578+
553579
function normalizeMapLikeValue(value: Record<string, unknown>): Record<string, unknown> {
554580
const output: Record<string, unknown> = {};
555581

@@ -842,6 +868,14 @@ export function field(_path: string): Field {
842868
return createField(_path);
843869
}
844870

871+
/**
872+
* @beta
873+
* Returns a variable reference for alias-bound pipeline expressions.
874+
*/
875+
export function variable(_name: string): Expression {
876+
return createVariable(_name);
877+
}
878+
845879
/**
846880
* @beta
847881
* Logical AND of boolean expressions.
@@ -1004,9 +1038,6 @@ export function arrayContainsAll(
10041038
/**
10051039
* @beta
10061040
* Filters an array using a provided alias and predicate expression.
1007-
*
1008-
* The alias is serialized for native/web SDKs that support variable-bound
1009-
* predicates; RN Firebase does not yet expose the `variable()` helper.
10101041
*/
10111042
export function arrayFilter(
10121043
_fieldName: string,

packages/firestore/lib/pipelines/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export type { OneOf } from './types';
6767
export { execute } from './pipeline_impl';
6868
export {
6969
field,
70+
variable,
7071
and,
7172
or,
7273
greaterThan,

packages/firestore/lib/types/internal.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ export interface FirestorePipelineConstantExpressionInternal {
110110
value: FirestorePipelineSerializedValueInternal;
111111
}
112112

113+
/** Serialized variable expression node passed to native pipeline execute bridge. */
114+
export interface FirestorePipelineVariableExpressionInternal {
115+
__kind?: 'expression';
116+
exprType: 'Variable';
117+
name: string;
118+
}
119+
113120
/** Serialized function expression node passed to native pipeline execute bridge. */
114121
export interface FirestorePipelineFunctionExpressionInternal {
115122
__kind?: 'expression';
@@ -160,6 +167,7 @@ export interface FirestorePipelineAliasedAggregateInternal {
160167
export type FirestorePipelineExpressionInternal =
161168
| FirestorePipelineFieldExpressionInternal
162169
| FirestorePipelineConstantExpressionInternal
170+
| FirestorePipelineVariableExpressionInternal
163171
| FirestorePipelineFunctionExpressionInternal;
164172

165173
export type FirestorePipelineSelectableInternal =

packages/firestore/lib/web/pipelines/pipeline_node_builder.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ function isExpressionNode(value: Record<string, unknown>): boolean {
5757
value.__kind === 'expression' ||
5858
value.exprType === 'Field' ||
5959
value.exprType === 'Constant' ||
60+
value.exprType === 'Variable' ||
6061
value.exprType === 'Function'
6162
);
6263
}
@@ -168,6 +169,11 @@ function rebuildExpressionNode(
168169
return;
169170
}
170171

172+
if (node.exprType === 'Variable' && typeof node.name === 'string') {
173+
resolve(getPipelineHelper('variable')(node.name) as Expression);
174+
return;
175+
}
176+
171177
if (typeof node.name === 'string') {
172178
const helperName = node.name;
173179
const args = Array.isArray(node.args) ? node.args : [];

0 commit comments

Comments
 (0)