Skip to content

Commit 35a361d

Browse files
committed
Implement support for genericStage and genericFunction
1 parent dbe6821 commit 35a361d

File tree

3 files changed

+85
-11
lines changed

3 files changed

+85
-11
lines changed

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

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,6 +2175,29 @@ export class Constant extends Expr {
21752175
}
21762176
}
21772177

2178+
/**
2179+
* Internal only
2180+
* @internal
2181+
* @private
2182+
*/
2183+
export class MapValue extends Expr {
2184+
constructor(private plainObject: Map<string, Expr>) {
2185+
super();
2186+
}
2187+
2188+
exprType: ExprType = 'Constant';
2189+
2190+
_readUserData(dataReader: UserDataReader): void {
2191+
this.plainObject.forEach(expr => {
2192+
expr._readUserData(dataReader);
2193+
});
2194+
}
2195+
2196+
_toProto(serializer: JsonProtoSerializer): ProtoValue {
2197+
return toMapValue(serializer, this.plainObject);
2198+
}
2199+
}
2200+
21782201
/**
21792202
* @beta
21802203
*
@@ -2214,6 +2237,17 @@ export class FirestoreFunction extends Expr {
22142237
}
22152238
}
22162239

2240+
/**
2241+
* @beta
2242+
*/
2243+
export class GenericFunction
2244+
extends FirestoreFunction
2245+
implements FilterCondition, Accumulator
2246+
{
2247+
accumulator: true = true;
2248+
filterable: true = true;
2249+
}
2250+
22172251
/**
22182252
* @beta
22192253
*/
@@ -4098,6 +4132,28 @@ export function map(elements: Record<string, any>): MapFunction {
40984132
return new MapFunction(result);
40994133
}
41004134

4135+
/**
4136+
* Internal use only
4137+
* Converts a plainObject to a mapValue in the proto representation,
4138+
* rather than a functionValue+map that is the result of the map(...) function.
4139+
* This behaves different than Constant.of(plainObject) because it
4140+
* traverses the input object, converts values in the object to expressions,
4141+
* and calls _readUserData on each of these expressions.
4142+
* @private
4143+
* @internal
4144+
* @param plainObject
4145+
*/
4146+
export function _mapValue(plainObject: Record<string, any>): MapValue {
4147+
const result: Map<string, Expr> = new Map<string, Expr>();
4148+
for (const key in plainObject) {
4149+
if (Object.prototype.hasOwnProperty.call(plainObject, key)) {
4150+
const value = plainObject[key];
4151+
result.set(key, valueToDefaultExpr(value));
4152+
}
4153+
}
4154+
return new MapValue(result);
4155+
}
4156+
41014157
export function array(elements: any[]): ArrayFunction {
41024158
return new ArrayFunction(
41034159
elements.map(element => valueToDefaultExpr(element))
@@ -7499,15 +7555,15 @@ export function timestampSub(
74997555
* genericFunction("sum", [Field.of("price")]);
75007556
* ```
75017557
*
7502-
* @param name The name of the user defined function.
7558+
* @param functionName The name of the user defined function.
75037559
* @param params The arguments to pass to the function.
7504-
* @return A new {@code Function} representing the function call.
7560+
* @return A new {@code GenericFucntion} representing the function call.
75057561
*/
75067562
export function genericFunction(
7507-
name: string,
7508-
params: Expr[]
7509-
): FirestoreFunction {
7510-
return new FirestoreFunction(name, params);
7563+
functionName: string,
7564+
params: any[]
7565+
): GenericFunction {
7566+
return new GenericFunction(functionName, params.map(valueToDefaultExpr));
75117567
}
75127568

75137569
/**

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { isPlainObject } from '../util/input_validation';
3434
import { getDatastore } from './components';
3535
import { Firestore } from './database';
3636
import {
37+
_mapValue,
3738
Accumulator,
3839
AccumulatorTarget,
3940
Constant,
@@ -672,12 +673,27 @@ export class Pipeline implements ProtoSerializable<ExecutePipelineRequest> {
672673
*/
673674
genericStage(name: string, params: any[]): Pipeline {
674675
const copy = this.stages.map(s => s);
675-
params.forEach(param => {
676+
677+
// Convert input values to Expressions.
678+
// We treat objects as mapValues and arrays as arrayValues,
679+
// this is unlike the default conversion for objects and arrays
680+
// passed to an expression.
681+
const expressionParams = params.map((value: any) => {
682+
if (value instanceof Expr) {
683+
return value;
684+
} else if (isPlainObject(value)) {
685+
return _mapValue(value);
686+
} else {
687+
return Constant.of(value);
688+
}
689+
});
690+
691+
expressionParams.forEach(param => {
676692
if (isReadableUserData(param)) {
677693
param._readUserData(this.userDataReader);
678694
}
679695
});
680-
copy.push(new GenericStage(name, params));
696+
copy.push(new GenericStage(name, expressionParams));
681697
return this.newPipeline(
682698
this._db,
683699
this.userDataReader,

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,14 +384,16 @@ export class Sort implements Stage {
384384
* @beta
385385
*/
386386
export class GenericStage implements Stage {
387-
constructor(public name: string, params: unknown[]) {}
387+
constructor(public name: string, private params: Expr[]) {}
388388

389389
/**
390390
* @internal
391391
* @private
392392
*/
393393
_toProto(serializer: JsonProtoSerializer): ProtoStage {
394-
// TODO support generic stage
395-
return {};
394+
return {
395+
name: this.name,
396+
args: this.params.map(o => o._toProto(serializer))
397+
};
396398
}
397399
}

0 commit comments

Comments
 (0)