Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Markduckworth/ppl mep #8801

Merged
merged 79 commits into from
Mar 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
e23ecfb
Multiple entry points for main package.
MarkDuckworth Dec 18, 2024
8006776
MEP for firestore lite building
MarkDuckworth Dec 19, 2024
db00e40
Fix issue with external exports
MarkDuckworth Dec 19, 2024
de97518
Refactor to support multiple entry points for the lite SDK. Fixes imp…
MarkDuckworth Dec 20, 2024
9c373ec
Type and comment cleanup
MarkDuckworth Jan 9, 2025
8b03745
Make PipelineSource generic and remove useFluentPipelines
MarkDuckworth Jan 9, 2025
2e1c8f6
Remove converter and placeholders for converter.
MarkDuckworth Jan 9, 2025
d67807e
cleanup: remove documentReferenceFactory
MarkDuckworth Jan 9, 2025
ea5c8e1
Linting and formatting
MarkDuckworth Jan 9, 2025
f251a04
Update the typings export for pipelines and lite pipelines so that it…
MarkDuckworth Jan 9, 2025
718ba98
Add missing Expr export
MarkDuckworth Jan 10, 2025
99ca193
Lint fixes
MarkDuckworth Jan 10, 2025
c911f97
TODO cleanup
MarkDuckworth Jan 10, 2025
229b0c7
update api review
MarkDuckworth Jan 10, 2025
0522ea7
Query to Proto with integration tests
MarkDuckworth Jan 22, 2025
50a65e4
API tweaks from review. Selectable, FilterCondition, and Accumulator …
MarkDuckworth Jan 23, 2025
d2291d0
Remove console.log statements from prune-dts.ts
MarkDuckworth Jan 27, 2025
d437b8e
Merge branch 'feat/pipelines' of github.com:firebase/firebase-js-sdk …
MarkDuckworth Jan 27, 2025
f44ea4d
code cleanup in prune-dts
MarkDuckworth Jan 27, 2025
16cfd24
Add missing imports to pipelines.ts
MarkDuckworth Jan 27, 2025
7d6aec1
If argument to FunctionExpr is a plain object or array, convert these…
MarkDuckworth Jan 29, 2025
e923dfd
Add tests for evaluating expressions in arrays and maps
MarkDuckworth Jan 29, 2025
29149c0
implement new FunctionExpressions as standalone functions
MarkDuckworth Feb 13, 2025
dbe6821
Fix typo and formatting in pipeline.test.ts
MarkDuckworth Feb 13, 2025
35a361d
Implement support for genericStage and genericFunction
MarkDuckworth Feb 13, 2025
da71f9a
Implement new function expressions as methods on the Expr class.
MarkDuckworth Feb 19, 2025
a06589a
Merge branch 'feat/pipelines' of github.com:firebase/firebase-js-sdk …
MarkDuckworth Feb 19, 2025
e820ee5
Pipeline test reorganization
MarkDuckworth Feb 19, 2025
33f5811
Implementing new stages Sample, Union, Unnest, Replace
MarkDuckworth Feb 21, 2025
ac42e1f
Rename FilterCondition to BooleanExpr
MarkDuckworth Feb 21, 2025
06d72b4
Update functions with variadic params to match signatures of the backend
MarkDuckworth Feb 22, 2025
b3d1f0c
Fix and implementation.
MarkDuckworth Feb 24, 2025
6c79ddd
Refactor AggregateFunction out of Expr
MarkDuckworth Feb 24, 2025
c4593b5
Add ScalarExpr class and make Expr a base class of AggregateFunction
MarkDuckworth Feb 25, 2025
db9ee0a
fixing missing imports and renames
MarkDuckworth Feb 25, 2025
ef1e42e
Remove classes for individual function types
MarkDuckworth Feb 25, 2025
c40ea12
Separate scalar expressions and aggregate functions into different cl…
MarkDuckworth Feb 25, 2025
3b38688
Remove deleted Expr classes from the pipelines exports
MarkDuckworth Feb 26, 2025
83e2cfe
Replace not(fn()) with notFn() in the query to pipeline conversion
MarkDuckworth Feb 26, 2025
4526ad1
Fix circular dependency between user_data_reader and expressions
MarkDuckworth Feb 26, 2025
2e981af
removing modular pipeline creation and removing fluent pipline execut…
MarkDuckworth Feb 26, 2025
a42b0d1
Change return type of execute from PipelineResult[] to PipelineSnapshot
MarkDuckworth Feb 26, 2025
8a06e25
Renames for API review: FunctionExpr, BooleanExpr, params
MarkDuckworth Feb 28, 2025
4e339ee
missing readonly
MarkDuckworth Feb 28, 2025
b303ec5
Build and test fixes
MarkDuckworth Feb 28, 2025
67f15fb
Replace Field.of() with field()
MarkDuckworth Feb 28, 2025
d31cf63
Add missing export PipelineSnaphsot
MarkDuckworth Feb 28, 2025
58d15c2
Replace Constant.of() with constant()
MarkDuckworth Feb 28, 2025
3268c63
Removed constant(...) overloads to create a map or array. Use the arr…
MarkDuckworth Feb 28, 2025
b909af7
Implemented and documented ascending|descending(fieldName) as a conve…
MarkDuckworth Feb 28, 2025
36def6e
fix tests creating a constant map and array
MarkDuckworth Feb 28, 2025
f1c68a5
Remove genericFunction, genericAggregateFunction, and genericBooleanE…
MarkDuckworth Feb 28, 2025
406929f
Pipeline result timestamp testing
MarkDuckworth Mar 3, 2025
9f1abbb
Testing timestamp edge cases
MarkDuckworth Mar 3, 2025
57c2a56
Query to pipeline conversion is performed from the PipelineSource cla…
MarkDuckworth Mar 3, 2025
0eda1ac
Timestamp tests and fix pipeline tests for change in pipeline creatio…
MarkDuckworth Mar 5, 2025
38d5052
test fix
MarkDuckworth Mar 6, 2025
c7beb1d
Refactor and rename all functions to match API proposal changes after…
MarkDuckworth Mar 6, 2025
5cc68d2
Fix build issues
MarkDuckworth Mar 6, 2025
2ccdac6
New integration util pipeline_export file to support the pipelines su…
MarkDuckworth Mar 6, 2025
cfb0879
Rename several FunctionExpr standalone exports from <name>Function to…
MarkDuckworth Mar 6, 2025
03fd4dd
Removing the all-packages api report script because it is no longer n…
MarkDuckworth Mar 6, 2025
ec03a5e
Remove any from the public api surface
MarkDuckworth Mar 6, 2025
458412c
lint fix
MarkDuckworth Mar 6, 2025
a7b5deb
Code cleanup
MarkDuckworth Mar 7, 2025
f6cc94b
FindNearest integration tests
MarkDuckworth Mar 7, 2025
96e3d19
Filling in gaps in test coverage
MarkDuckworth Mar 10, 2025
fc61479
Implement Pipeline tests for the lite SDK
MarkDuckworth Mar 12, 2025
68b8a76
Fixed a build issue with the lite SDK
MarkDuckworth Mar 12, 2025
225edeb
Improved error message context when invalid user data is passed to a …
MarkDuckworth Mar 12, 2025
8f819f8
Fix typo in old error message
MarkDuckworth Mar 12, 2025
df746b4
Fix lite pipeline exports
MarkDuckworth Mar 12, 2025
d55be8a
Merge branch 'main' of github.com:firebase/firebase-js-sdk into markd…
MarkDuckworth Mar 12, 2025
898ea70
api-review files
MarkDuckworth Mar 12, 2025
fa56207
Merge branch 'feat/pipelines' into markduckworth/ppl-mep
MarkDuckworth Mar 12, 2025
58db6bf
Fixing tests and improving test coverage
MarkDuckworth Mar 21, 2025
129b62b
PR feedback
MarkDuckworth Mar 21, 2025
4469c58
Updating replaceWith to take an Expr
MarkDuckworth Mar 21, 2025
ddc7a6f
yarn format
MarkDuckworth Mar 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,147 changes: 721 additions & 1,426 deletions common/api-review/firestore-lite-pipelines.api.md

Large diffs are not rendered by default.

1,435 changes: 690 additions & 745 deletions common/api-review/firestore-pipelines.api.md

Large diffs are not rendered by default.

1,343 changes: 8 additions & 1,335 deletions common/api-review/firestore.api.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/firestore/lite/pipelines/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"module": "../../dist/lite/pipelines.browser.esm2017.js",
"browser": "../../dist/lite/pipelines.browser.esm2017.js",
"react-native": "../../dist/lite/pipelines.rn.esm2017.js",
"typings": "../../dist/lite/pipelines.d.ts",
"typings": "./pipelines.d.ts",
"private": true,
"engines": {
"node": ">=18.0.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/firestore/lite/pipelines/pipelines.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { PipelineSource, Pipeline } from '../../dist/lite/pipelines';
// Augument the Firestore class with the pipeline() method.
// This is stripped from dist/lite/pipelines.d.ts during the build
// so it needs to be re-added here.
declare module '@firebase/firestore' {
declare module '@firebase/firestore/lite' {
interface Firestore {
pipeline(): PipelineSource<Pipeline>;
}
Expand Down
108 changes: 39 additions & 69 deletions packages/firestore/lite/pipelines/pipelines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,14 @@ export type {

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

export { PipelineResult } from '../../src/lite-api/pipeline-result';
export {
PipelineResult,
PipelineSnapshot
} from '../../src/lite-api/pipeline-result';

export { Pipeline } from '../../src/lite-api/pipeline';

export { pipeline, execute } from '../../src/lite-api/pipeline_impl';
export { execute } from '../../src/lite-api/pipeline_impl';

export {
Stage,
Expand All @@ -76,14 +79,44 @@ export {
} from '../../src/lite-api/stage';

export {
Expr,
field,
and,
array,
arrayOffset,
constant,
add,
subtract,
multiply,
avg,
bitAnd,
substr,
constantVector,
bitLeftShift,
bitNot,
count,
mapMerge,
mapRemove,
bitOr,
ifError,
isAbsent,
isError,
or,
rand,
bitRightShift,
bitXor,
divide,
isNotNan,
map,
isNotNull,
isNull,
mod,
documentId,
eq,
neq,
lt,
countIf,
currentContext,
lte,
gt,
gte,
Expand Down Expand Up @@ -132,79 +165,16 @@ export {
timestampToUnixSeconds,
timestampAdd,
timestampSub,
genericFunction,
ascending,
descending,
ExprWithAlias,
Field,
Fields,
Constant,
FirestoreFunction,
Add,
Subtract,
Multiply,
Divide,
Mod,
Eq,
Neq,
Lt,
Lte,
Gt,
Gte,
ArrayConcat,
ArrayReverse,
ArrayContains,
ArrayContainsAll,
ArrayContainsAny,
ArrayLength,
ArrayElement,
EqAny,
IsNan,
Exists,
Not,
And,
Or,
Xor,
Cond,
LogicalMaximum,
LogicalMinimum,
Reverse,
ReplaceFirst,
ReplaceAll,
CharLength,
ByteLength,
Like,
RegexContains,
RegexMatch,
StrContains,
StartsWith,
EndsWith,
ToLower,
ToUpper,
Trim,
StrConcat,
MapGet,
Count,
Sum,
Avg,
Minimum,
Maximum,
CosineDistance,
DotProduct,
EuclideanDistance,
VectorLength,
UnixMicrosToTimestamp,
TimestampToUnixMicros,
UnixMillisToTimestamp,
TimestampToUnixMillis,
UnixSecondsToTimestamp,
TimestampToUnixSeconds,
TimestampAdd,
TimestampSub,
FunctionExpr,
Ordering,
ExprType,
AccumulatorTarget,
AggregateWithAlias,
Selectable,
FilterCondition,
Accumulator
BooleanExpr,
AggregateFunction
} from '../../src/lite-api/expressions';
5 changes: 2 additions & 3 deletions packages/firestore/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@
"test:minified": "(cd ../../integration/firestore ; yarn test)",
"trusted-type-check": "tsec -p tsconfig.json --noEmit",
"api-report:main": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore --packageRoot . --typescriptDts ./dist/firestore/src/index.d.ts --rollupDts ./dist/private.d.ts --untrimmedRollupDts ./dist/internal.d.ts --publicDts ./dist/index.d.ts",
"api-report:all-packages": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore --packageRoot . --typescriptDts ./dist/firestore/src/all_packages.d.ts --rollupDts ./dist/private.all_packages.d.ts --untrimmedRollupDts ./dist/internal.all_packages.d.ts --publicDts ./dist/all_packages.d.ts",
"api-report:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-pipelines --packageRoot . --typescriptDts ./dist/firestore/pipelines/pipelines.d.ts --rollupDts ./dist/private.pipelines.d.ts --untrimmedRollupDts ./dist/internal.pipelines.d.ts --publicDts ./dist/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/index.d.ts",
"api-report:lite": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite --packageRoot . --typescriptDts ./dist/firestore/lite/index.d.ts --rollupDts ./dist/lite/private.d.ts --untrimmedRollupDts ./dist/lite/internal.d.ts --publicDts ./dist/lite/index.d.ts",
"api-report:lite:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite-pipelines --packageRoot . --typescriptDts ./dist/firestore/lite/pipelines/pipelines.d.ts --rollupDts ./dist/lite/private.pipelines.d.ts --untrimmedRollupDts ./dist/lite/internal.pipelines.d.ts --publicDts ./dist/lite/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/index.d.ts",
"api-report:lite:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite-pipelines --packageRoot . --typescriptDts ./dist/firestore/lite/pipelines/pipelines.d.ts --rollupDts ./dist/lite/private.pipelines.d.ts --untrimmedRollupDts ./dist/lite/internal.pipelines.d.ts --publicDts ./dist/lite/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/lite/index.d.ts",
"api-report:api-json": "rm -rf temp && api-extractor run --local --verbose",
"api-report": "run-s --npm-path npm api-report:main api-report:pipelines api-report:all-packages api-report:lite api-report:lite:pipelines && yarn api-report:api-json",
"api-report": "run-s --npm-path npm api-report:main api-report:pipelines api-report:lite api-report:lite:pipelines && yarn api-report:api-json",
"doc": "api-documenter markdown --input temp --output docs",
"typings:public": "node ../../scripts/build/use_typings.js ./dist/all-packages.d.ts"
},
Expand Down
7 changes: 2 additions & 5 deletions packages/firestore/pipelines/pipelines.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {PipelineSource, Pipeline} from "../dist/pipelines";
import { PipelineSource, Pipeline } from '../dist/pipelines';

// Augument the Firestore and Query classes with the pipeline() method.
// This is stripped from dist/lite/pipelines.d.ts during the build
Expand All @@ -23,9 +23,6 @@ declare module '@firebase/firestore' {
interface Firestore {
pipeline(): PipelineSource<Pipeline>;
}
interface Query {
pipeline(): Pipeline;
}
}

export * from "../dist/pipelines";
export * from '../dist/pipelines';
3 changes: 1 addition & 2 deletions packages/firestore/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,7 @@ export { isBase64Available as _isBase64Available } from './platform/base64';
export { DatabaseId as _DatabaseId } from './core/database_info';
export {
_internalQueryToProtoQueryTarget,
_internalAggregationQueryToProtoRunAggregationQueryRequest,
_internalPipelineToExecutePipelineRequestProto
_internalAggregationQueryToProtoRunAggregationQueryRequest
} from './remote/internal_serializer';
export {
cast as _cast,
Expand Down
45 changes: 45 additions & 0 deletions packages/firestore/src/api/parse_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,53 @@
*/

import { DatabaseId } from '../core/database_info';
import { UserDataSource } from '../lite-api/user_data_reader';
import { DocumentKey } from '../model/document_key';
import { FieldTransform } from '../model/mutation';
import { FieldPath as InternalFieldPath } from '../model/path';
import { JsonProtoSerializer } from '../remote/serializer';
import { FirestoreError } from '../util/error';

/** Contains the settings that are mutated as we parse user data. */
export interface ContextSettings {
/** Indicates what kind of API method this data came from. */
readonly dataSource: UserDataSource;
/** The name of the method the user called to create the ParseContext. */
readonly methodName: string;
/** The document the user is attempting to modify, if that applies. */
readonly targetDoc?: DocumentKey;
/**
* A path within the object being parsed. This could be an empty path (in
* which case the context represents the root of the data being parsed), or a
* nonempty path (indicating the context represents a nested location within
* the data).
*/
readonly path?: InternalFieldPath;
/**
* Whether or not this context corresponds to an element of an array.
* If not set, elements are treated as if they were outside of arrays.
*/
readonly arrayElement?: boolean;
/**
* Whether or not a converter was specified in this context. If true, error
* messages will reference the converter when invalid data is provided.
*/
readonly hasConverter?: boolean;
}

export interface ParseContext {
readonly settings: ContextSettings;
readonly databaseId: DatabaseId;
readonly serializer: JsonProtoSerializer;
readonly ignoreUndefinedProperties: boolean;
fieldTransforms: FieldTransform[];
fieldMask: InternalFieldPath[];
get path(): InternalFieldPath | undefined;
get dataSource(): UserDataSource;
contextWith(configuration: Partial<ContextSettings>): ParseContext;
childContextForField(field: string): ParseContext;
childContextForFieldPath(field: InternalFieldPath): ParseContext;
childContextForArray(index: number): ParseContext;
createError(reason: string): FirestoreError;
contains(fieldPath: InternalFieldPath): boolean;
}
66 changes: 2 additions & 64 deletions packages/firestore/src/api/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,12 @@
* limitations under the License.
*/

import { firestoreClientExecutePipeline } from '../core/firestore_client';
import { Pipeline as LitePipeline } from '../lite-api/pipeline';
import { PipelineResult } from '../lite-api/pipeline-result';
import { DocumentReference } from '../lite-api/reference';
import { Stage } from '../lite-api/stage';
import { UserDataReader } from '../lite-api/user_data_reader';
import { AbstractUserDataWriter } from '../lite-api/user_data_writer';
import { cast } from '../util/input_validation';

import { ensureFirestoreConfigured, Firestore } from './database';
import { Firestore } from './database';

export class Pipeline extends LitePipeline {
/**
Expand All @@ -41,66 +37,8 @@ export class Pipeline extends LitePipeline {
db: Firestore,
userDataReader: UserDataReader,
userDataWriter: AbstractUserDataWriter,
stages: Stage[],
converter: unknown = {}
stages: Stage[]
): Pipeline {
return new Pipeline(db, userDataReader, userDataWriter, stages);
}

/**
* Executes this pipeline and returns a Promise to represent the asynchronous operation.
*
* <p>The returned Promise can be used to track the progress of the pipeline execution
* and retrieve the results (or handle any errors) asynchronously.
*
* <p>The pipeline results are returned as a list of {@link PipelineResult} objects. Each {@link
* PipelineResult} typically represents a single key/value map that has passed through all the
* stages of the pipeline, however this might differ depending on the stages involved in the
* pipeline. For example:
*
* <ul>
* <li>If there are no stages or only transformation stages, each {@link PipelineResult}
* represents a single document.</li>
* <li>If there is an aggregation, only a single {@link PipelineResult} is returned,
* representing the aggregated results over the entire dataset .</li>
* <li>If there is an aggregation stage with grouping, each {@link PipelineResult} represents a
* distinct group and its associated aggregated values.</li>
* </ul>
*
* <p>Example:
*
* ```typescript
* const futureResults = await firestore.pipeline().collection("books")
* .where(gt(Field.of("rating"), 4.5))
* .select("title", "author", "rating")
* .execute();
* ```
*
* @return A Promise representing the asynchronous pipeline execution.
*/
execute(): Promise<PipelineResult[]> {
const firestore = cast(this._db, Firestore);
const client = ensureFirestoreConfigured(firestore);
return firestoreClientExecutePipeline(client, this).then(result => {
const docs = result
// Currently ignore any response from ExecutePipeline that does
// not contain any document data in the `fields` property.
.filter(element => !!element.fields)
.map(
element =>
new PipelineResult(
this._userDataWriter,
element.key?.path
? new DocumentReference(firestore, null, element.key)
: undefined,
element.fields,
element.executionTime?.toTimestamp(),
element.createTime?.toTimestamp(),
element.updateTime?.toTimestamp()
)
);

return docs;
});
}
}
Loading
Loading