Skip to content

Commit 527131c

Browse files
committed
Pipeline and stage options. Tangential renames and minor fixes
1 parent 5e9b24d commit 527131c

22 files changed

+2621
-779
lines changed

packages/firestore/lite/pipelines/pipelines.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ export type {
5050

5151
export { PipelineSource } from '../../src/lite-api/pipeline-source';
5252

53+
export { OneOf } from '../../src/util/types';
54+
5355
export {
5456
PipelineResult,
5557
PipelineSnapshot
@@ -59,9 +61,30 @@ export { Pipeline } from '../../src/lite-api/pipeline';
5961

6062
export { execute } from '../../src/lite-api/pipeline_impl';
6163

64+
export {
65+
StageOptions,
66+
CollectionStageOptions,
67+
CollectionGroupStageOptions,
68+
DatabaseStageOptions,
69+
DocumentsStageOptions,
70+
AddFieldsStageOptions,
71+
RemoveFieldsStageOptions,
72+
SelectStageOptions,
73+
WhereStageOptions,
74+
OffsetStageOptions,
75+
LimitStageOptions,
76+
DistinctStageOptions,
77+
AggregateStageOptions,
78+
FindNearestStageOptions,
79+
ReplaceWithStageOptions,
80+
SampleStageOptions,
81+
UnionStageOptions,
82+
UnnestStageOptions,
83+
SortStageOptions
84+
} from '../../src/lite-api/stage_options';
85+
6286
export {
6387
Stage,
64-
FindNearestOptions,
6588
AddFields,
6689
Aggregate,
6790
Distinct,
@@ -83,7 +106,6 @@ export {
83106
field,
84107
and,
85108
array,
86-
arrayOffset,
87109
constant,
88110
add,
89111
subtract,

packages/firestore/src/api/pipeline_impl.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
import { Pipeline as LitePipeline } from '../lite-api/pipeline';
2525
import { PipelineResult, PipelineSnapshot } from '../lite-api/pipeline-result';
2626
import { PipelineSource } from '../lite-api/pipeline-source';
27-
import { PipelineOptions } from '../lite-api/pipeline_settings';
27+
import { PipelineOptions } from '../lite-api/pipeline_options';
2828
import { Stage } from '../lite-api/stage';
2929
import {
3030
newUserDataReader,
@@ -91,7 +91,6 @@ export function execute(
9191
};
9292

9393
const { pipeline, customOptions, ...rest } = options;
94-
const genericOptions: { [name:string]: unknown } = customOptions ?? {};
9594

9695
const firestore = cast(pipeline._db, Firestore);
9796
const client = ensureFirestoreConfigured(firestore);
@@ -102,8 +101,8 @@ export function execute(
102101
);
103102
const context = udr.createContext(UserDataSource.Argument, 'execute');
104103

105-
const structuredPipelineOptions = new StructuredPipelineOptions(rest, genericOptions);
106-
structuredPipelineOptions._readUserData(udr, context);
104+
const structuredPipelineOptions = new StructuredPipelineOptions(rest, customOptions);
105+
structuredPipelineOptions._readUserData(context);
107106

108107
const structuredPipeline: StructuredPipeline = new StructuredPipeline(
109108
pipeline,
@@ -142,10 +141,12 @@ export function execute(
142141

143142
// Augment the Firestore class with the pipeline() factory method
144143
Firestore.prototype.pipeline = function (): PipelineSource<Pipeline> {
145-
return new PipelineSource<Pipeline>(this._databaseId, (stages: Stage[]) => {
144+
const userDataReader =
145+
newUserDataReader(this);
146+
return new PipelineSource<Pipeline>(this._databaseId, userDataReader, (stages: Stage[]) => {
146147
return new Pipeline(
147148
this,
148-
newUserDataReader(this),
149+
userDataReader,
149150
new ExpUserDataWriter(this),
150151
stages
151152
);

packages/firestore/src/api_pipelines.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
export { PipelineSource } from './lite-api/pipeline-source';
1919

20+
export { OneOf } from './util/types';
21+
2022
export {
2123
PipelineResult,
2224
PipelineSnapshot,
@@ -27,9 +29,32 @@ export { Pipeline } from './api/pipeline';
2729

2830
export { execute } from './api/pipeline_impl';
2931

32+
export { PipelineOptions } from './lite-api/pipeline_options';
33+
34+
export {
35+
StageOptions,
36+
CollectionStageOptions,
37+
CollectionGroupStageOptions,
38+
DatabaseStageOptions,
39+
DocumentsStageOptions,
40+
AddFieldsStageOptions,
41+
RemoveFieldsStageOptions,
42+
SelectStageOptions,
43+
WhereStageOptions,
44+
OffsetStageOptions,
45+
LimitStageOptions,
46+
DistinctStageOptions,
47+
AggregateStageOptions,
48+
FindNearestStageOptions,
49+
ReplaceWithStageOptions,
50+
SampleStageOptions,
51+
UnionStageOptions,
52+
UnnestStageOptions,
53+
SortStageOptions
54+
} from './lite-api/stage_options';
55+
3056
export {
3157
Stage,
32-
FindNearestOptions,
3358
AddFields,
3459
Aggregate,
3560
Distinct,
@@ -121,7 +146,7 @@ export {
121146
bitRightShift,
122147
rand,
123148
array,
124-
arrayOffset,
149+
arrayGet,
125150
isError,
126151
ifError,
127152
isAbsent,
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import {ParseContext} from "../api/parse_context";
16+
import {
17+
parseData,
18+
} from "../lite-api/user_data_reader";
19+
import { ObjectValue } from '../model/object_value';
20+
import { FieldPath } from '../model/path';
21+
import {ApiClientObjectMap, Value} from "../protos/firestore_proto_api";
22+
import {isPlainObject} from "../util/input_validation";
23+
import { mapToArray } from '../util/obj';
24+
export type OptionsDefinitions = Record<string, OptionDefinition>;
25+
export interface OptionDefinition {
26+
serverName: string;
27+
nestedOptions?: OptionsDefinitions;
28+
}
29+
30+
export class OptionsUtil {
31+
constructor(private optionDefinitions: OptionsDefinitions) {}
32+
33+
private _getKnownOptions(
34+
options: Record<string, unknown>,
35+
context: ParseContext
36+
): ObjectValue {
37+
const knownOptions: ObjectValue = ObjectValue.empty();
38+
39+
// SERIALIZE KNOWN OPTIONS
40+
for (const knownOptionKey in this.optionDefinitions) {
41+
if (this.optionDefinitions.hasOwnProperty(knownOptionKey)) {
42+
const optionDefinition: OptionDefinition =
43+
this.optionDefinitions[knownOptionKey];
44+
45+
if (knownOptionKey in options) {
46+
const optionValue: unknown = options[knownOptionKey];
47+
let protoValue: Value | undefined = undefined;
48+
49+
if (optionDefinition.nestedOptions && isPlainObject(optionValue)) {
50+
const nestedUtil = new OptionsUtil(optionDefinition.nestedOptions);
51+
protoValue = {
52+
mapValue: {
53+
fields: nestedUtil.getOptionsProto(context, optionValue),
54+
},
55+
};
56+
} else if (optionValue) {
57+
protoValue = parseData(optionValue, context) ?? undefined;
58+
}
59+
60+
if (protoValue) {
61+
knownOptions.set(
62+
FieldPath.fromServerFormat(optionDefinition.serverName),
63+
protoValue
64+
);
65+
}
66+
}
67+
}
68+
}
69+
70+
return knownOptions;
71+
}
72+
73+
getOptionsProto(
74+
context: ParseContext,
75+
knownOptions: Record<string, unknown>,
76+
optionsOverride?: Record<string, unknown>
77+
): ApiClientObjectMap<Value> | undefined {
78+
const result: ObjectValue = this._getKnownOptions(knownOptions, context);
79+
80+
// APPLY OPTIONS OVERRIDES
81+
if (optionsOverride) {
82+
const optionsMap = new Map(
83+
mapToArray(optionsOverride, (value, key) => [
84+
FieldPath.fromServerFormat(key),
85+
value !== undefined ? parseData(value, context) : null,
86+
])
87+
);
88+
result.setAll(optionsMap);
89+
}
90+
91+
// Return MapValue from `result` or empty map value
92+
return result.value.mapValue.fields ?? {};
93+
}
94+
}

packages/firestore/src/core/pipeline-util.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ function reverseOrderings(orderings: Ordering[]): Ordering[] {
161161
o =>
162162
new Ordering(
163163
o.expr,
164-
o.direction === 'ascending' ? 'descending' : 'ascending'
164+
o.direction === 'ascending' ? 'descending' : 'ascending',
165+
undefined
165166
)
166167
);
167168
}

packages/firestore/src/core/structured_pipeline.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717

1818
import {ParseContext} from "../api/parse_context";
19-
import {UserDataReader, UserDataSource} from "../lite-api/user_data_reader";
19+
import {UserData} from "../lite-api/user_data_reader";
2020
import {
2121
ApiClientObjectMap, firestoreV1ApiClientInterfaces,
2222
Pipeline as PipelineProto,
@@ -25,7 +25,6 @@ import {
2525
import {
2626
JsonProtoSerializer,
2727
ProtoSerializable,
28-
UserData
2928
} from '../remote/serializer';
3029

3130
import {OptionsUtil} from "./options_util";
@@ -43,10 +42,7 @@ export class StructuredPipelineOptions implements UserData{
4342
private _userOptions: Record<string, unknown> = {},
4443
private _optionsOverride: Record<string, unknown> = {}) {}
4544

46-
_readUserData(dataReader: UserDataReader, context?: ParseContext): void {
47-
if (!context) {
48-
context = dataReader.createContext(UserDataSource.Argument, "StructuredPipelineOptions._readUserData");
49-
}
45+
_readUserData(context: ParseContext): void {
5046
this.proto = this.optionsUtil.getOptionsProto(context, this._userOptions, this._optionsOverride);
5147
}
5248
}

0 commit comments

Comments
 (0)