From c694fb8a26e900403edcc57937baf47307dc2f88 Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Fri, 6 Feb 2026 11:19:09 +0000 Subject: [PATCH 1/5] feat(firestore): add support for Pipeline APIs --- .../cloud_firestore/lib/cloud_firestore.dart | 9 + .../lib/pipeline_snapshot.dart | 26 + .../cloud_firestore/lib/src/firestore.dart | 19 + .../cloud_firestore/lib/src/pipeline.dart | 477 ++++++++++++++++++ .../lib/src/pipeline_aggregate.dart | 58 +++ .../lib/src/pipeline_distance.dart | 17 + .../lib/src/pipeline_expression.dart | 394 +++++++++++++++ .../lib/src/pipeline_ordering.dart | 30 ++ .../lib/src/pipeline_sample.dart | 43 ++ .../lib/src/pipeline_source.dart | 66 +++ .../lib/src/pipeline_stage.dart | 387 ++++++++++++++ .../cloud_firestore_platform_interface.dart | 1 + .../platform_interface_firestore.dart | 8 + .../platform_interface_pipeline_snapshot.dart | 40 ++ 14 files changed, 1575 insertions(+) create mode 100644 packages/cloud_firestore/cloud_firestore/lib/pipeline_snapshot.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_distance.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_sample.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart create mode 100644 packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline_snapshot.dart diff --git a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart index 6efbb19345ce..c84108ac3686 100755 --- a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart @@ -53,7 +53,16 @@ part 'src/filters.dart'; part 'src/firestore.dart'; part 'src/load_bundle_task.dart'; part 'src/load_bundle_task_snapshot.dart'; +part 'pipeline_snapshot.dart'; part 'src/persistent_cache_index_manager.dart'; +part 'src/pipeline.dart'; +part 'src/pipeline_aggregate.dart'; +part 'src/pipeline_distance.dart'; +part 'src/pipeline_expression.dart'; +part 'src/pipeline_ordering.dart'; +part 'src/pipeline_sample.dart'; +part 'src/pipeline_source.dart'; +part 'src/pipeline_stage.dart'; part 'src/query.dart'; part 'src/query_document_snapshot.dart'; part 'src/query_snapshot.dart'; diff --git a/packages/cloud_firestore/cloud_firestore/lib/pipeline_snapshot.dart b/packages/cloud_firestore/cloud_firestore/lib/pipeline_snapshot.dart new file mode 100644 index 000000000000..f08cb6735987 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/pipeline_snapshot.dart @@ -0,0 +1,26 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of 'cloud_firestore.dart'; + +/// Result of executing a pipeline +class PipelineResult { + final DocumentReference> document; + final DateTime createTime; + final DateTime updateTime; + + PipelineResult({ + required this.document, + required this.createTime, + required this.updateTime, + }); +} + +/// Snapshot containing pipeline execution results +class PipelineSnapshot { + final List result; + final DateTime executionTime; + + PipelineSnapshot._(this.result, this.executionTime); +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart index 4f735629aee1..3e583c3f3331 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart @@ -339,6 +339,25 @@ class FirebaseFirestore extends FirebasePluginPlatform { return null; } + /// Returns a [PipelineSource] for creating and executing pipelines. + /// + /// Pipelines allow you to perform complex queries and transformations on + /// Firestore data using a fluent API. + /// + /// Example: + /// ```dart + /// final snapshot = await FirebaseFirestore.instance + /// .pipeline() + /// .collection('users') + /// .where(PipelineFilter(Field('age'), isGreaterThan: 18)) + /// .sort(Field('name').ascending()) + /// .limit(10) + /// .execute(); + /// ``` + PipelineSource pipeline() { + return PipelineSource._(this); + } + /// Configures indexing for local query execution. Any previous index configuration is overridden. /// /// The index entries themselves are created asynchronously. You can continue to use queries that diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart new file mode 100644 index 000000000000..e7849f43afd7 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart @@ -0,0 +1,477 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// A pipeline for querying and transforming Firestore data +class Pipeline { + final List _stages; + final FirebaseFirestore _firestore; + + Pipeline._(this._firestore, this._stages); + + /// Executes the pipeline and returns a snapshot of the results + Future execute() async { + final platformSnapshot = + await _firestore._delegate.executePipeline(_toSerializableStages()); + return _convertPlatformSnapshot(platformSnapshot); + } + + /// Converts platform snapshot to public snapshot + PipelineSnapshot _convertPlatformSnapshot( + PipelineSnapshotPlatform platformSnapshot) { + final results = platformSnapshot.results.map((platformResult) { + return PipelineResult( + document: _JsonDocumentReference( + _firestore, + platformResult.document, + ), + createTime: platformResult.createTime, + updateTime: platformResult.updateTime, + ); + }).toList(); + + return PipelineSnapshot._(results, platformSnapshot.executionTime); + } + + /// Converts stages to serializable format for platform communication + List> _toSerializableStages() { + return _stages.map((stage) => stage.toMap()).toList(); + } + + /// Public method to get serializable stages (used by union stage) + List> getSerializableStages() { + return _toSerializableStages(); + } + + // Pipeline Actions + + /// Adds fields to documents using expressions + Pipeline addFields( + PipelineExpression expression1, [ + PipelineExpression? expression2, + PipelineExpression? expression3, + PipelineExpression? expression4, + PipelineExpression? expression5, + PipelineExpression? expression6, + PipelineExpression? expression7, + PipelineExpression? expression8, + PipelineExpression? expression9, + PipelineExpression? expression10, + PipelineExpression? expression11, + PipelineExpression? expression12, + PipelineExpression? expression13, + PipelineExpression? expression14, + PipelineExpression? expression15, + PipelineExpression? expression16, + PipelineExpression? expression17, + PipelineExpression? expression18, + PipelineExpression? expression19, + PipelineExpression? expression20, + PipelineExpression? expression21, + PipelineExpression? expression22, + PipelineExpression? expression23, + PipelineExpression? expression24, + PipelineExpression? expression25, + PipelineExpression? expression26, + PipelineExpression? expression27, + PipelineExpression? expression28, + PipelineExpression? expression29, + PipelineExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + + return Pipeline._(_firestore, [ + ..._stages, + _AddFieldsStage(expressions), + ]); + } + + /// Aggregates data using aggregate functions + Pipeline aggregate( + PipelineAggregateFunction aggregateFunction1, [ + PipelineAggregateFunction? aggregateFunction2, + PipelineAggregateFunction? aggregateFunction3, + PipelineAggregateFunction? aggregateFunction4, + PipelineAggregateFunction? aggregateFunction5, + PipelineAggregateFunction? aggregateFunction6, + PipelineAggregateFunction? aggregateFunction7, + PipelineAggregateFunction? aggregateFunction8, + PipelineAggregateFunction? aggregateFunction9, + PipelineAggregateFunction? aggregateFunction10, + PipelineAggregateFunction? aggregateFunction11, + PipelineAggregateFunction? aggregateFunction12, + PipelineAggregateFunction? aggregateFunction13, + PipelineAggregateFunction? aggregateFunction14, + PipelineAggregateFunction? aggregateFunction15, + PipelineAggregateFunction? aggregateFunction16, + PipelineAggregateFunction? aggregateFunction17, + PipelineAggregateFunction? aggregateFunction18, + PipelineAggregateFunction? aggregateFunction19, + PipelineAggregateFunction? aggregateFunction20, + PipelineAggregateFunction? aggregateFunction21, + PipelineAggregateFunction? aggregateFunction22, + PipelineAggregateFunction? aggregateFunction23, + PipelineAggregateFunction? aggregateFunction24, + PipelineAggregateFunction? aggregateFunction25, + PipelineAggregateFunction? aggregateFunction26, + PipelineAggregateFunction? aggregateFunction27, + PipelineAggregateFunction? aggregateFunction28, + PipelineAggregateFunction? aggregateFunction29, + PipelineAggregateFunction? aggregateFunction30, + ]) { + final functions = [aggregateFunction1]; + if (aggregateFunction2 != null) functions.add(aggregateFunction2); + if (aggregateFunction3 != null) functions.add(aggregateFunction3); + if (aggregateFunction4 != null) functions.add(aggregateFunction4); + if (aggregateFunction5 != null) functions.add(aggregateFunction5); + if (aggregateFunction6 != null) functions.add(aggregateFunction6); + if (aggregateFunction7 != null) functions.add(aggregateFunction7); + if (aggregateFunction8 != null) functions.add(aggregateFunction8); + if (aggregateFunction9 != null) functions.add(aggregateFunction9); + if (aggregateFunction10 != null) functions.add(aggregateFunction10); + if (aggregateFunction11 != null) functions.add(aggregateFunction11); + if (aggregateFunction12 != null) functions.add(aggregateFunction12); + if (aggregateFunction13 != null) functions.add(aggregateFunction13); + if (aggregateFunction14 != null) functions.add(aggregateFunction14); + if (aggregateFunction15 != null) functions.add(aggregateFunction15); + if (aggregateFunction16 != null) functions.add(aggregateFunction16); + if (aggregateFunction17 != null) functions.add(aggregateFunction17); + if (aggregateFunction18 != null) functions.add(aggregateFunction18); + if (aggregateFunction19 != null) functions.add(aggregateFunction19); + if (aggregateFunction20 != null) functions.add(aggregateFunction20); + if (aggregateFunction21 != null) functions.add(aggregateFunction21); + if (aggregateFunction22 != null) functions.add(aggregateFunction22); + if (aggregateFunction23 != null) functions.add(aggregateFunction23); + if (aggregateFunction24 != null) functions.add(aggregateFunction24); + if (aggregateFunction25 != null) functions.add(aggregateFunction25); + if (aggregateFunction26 != null) functions.add(aggregateFunction26); + if (aggregateFunction27 != null) functions.add(aggregateFunction27); + if (aggregateFunction28 != null) functions.add(aggregateFunction28); + if (aggregateFunction29 != null) functions.add(aggregateFunction29); + if (aggregateFunction30 != null) functions.add(aggregateFunction30); + + return Pipeline._(_firestore, [ + ..._stages, + _AggregateStage(functions), + ]); + } + + /// Gets distinct values based on expressions + Pipeline distinct( + PipelineExpression expression1, [ + PipelineExpression? expression2, + PipelineExpression? expression3, + PipelineExpression? expression4, + PipelineExpression? expression5, + PipelineExpression? expression6, + PipelineExpression? expression7, + PipelineExpression? expression8, + PipelineExpression? expression9, + PipelineExpression? expression10, + PipelineExpression? expression11, + PipelineExpression? expression12, + PipelineExpression? expression13, + PipelineExpression? expression14, + PipelineExpression? expression15, + PipelineExpression? expression16, + PipelineExpression? expression17, + PipelineExpression? expression18, + PipelineExpression? expression19, + PipelineExpression? expression20, + PipelineExpression? expression21, + PipelineExpression? expression22, + PipelineExpression? expression23, + PipelineExpression? expression24, + PipelineExpression? expression25, + PipelineExpression? expression26, + PipelineExpression? expression27, + PipelineExpression? expression28, + PipelineExpression? expression29, + PipelineExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + + return Pipeline._(_firestore, [ + ..._stages, + _DistinctStage(expressions), + ]); + } + + /// Finds nearest vectors using vector similarity search + Pipeline findNearest( + Field vectorField, + List vectorValue, + DistanceMeasure distanceMeasure, { + int? limit, + }) { + return Pipeline._(_firestore, [ + ..._stages, + _FindNearestStage(vectorField, vectorValue, distanceMeasure, + limit: limit), + ]); + } + + /// Limits the number of results + Pipeline limit(int limit) { + return Pipeline._(_firestore, [ + ..._stages, + _LimitStage(limit), + ]); + } + + /// Offsets the results + Pipeline offset(int offset) { + return Pipeline._(_firestore, [ + ..._stages, + _OffsetStage(offset), + ]); + } + + /// Removes specified fields from documents + Pipeline removeFields( + String fieldPath1, [ + String? fieldPath2, + String? fieldPath3, + String? fieldPath4, + String? fieldPath5, + String? fieldPath6, + String? fieldPath7, + String? fieldPath8, + String? fieldPath9, + String? fieldPath10, + String? fieldPath11, + String? fieldPath12, + String? fieldPath13, + String? fieldPath14, + String? fieldPath15, + String? fieldPath16, + String? fieldPath17, + String? fieldPath18, + String? fieldPath19, + String? fieldPath20, + String? fieldPath21, + String? fieldPath22, + String? fieldPath23, + String? fieldPath24, + String? fieldPath25, + String? fieldPath26, + String? fieldPath27, + String? fieldPath28, + String? fieldPath29, + String? fieldPath30, + ]) { + final fieldPaths = [fieldPath1]; + if (fieldPath2 != null) fieldPaths.add(fieldPath2); + if (fieldPath3 != null) fieldPaths.add(fieldPath3); + if (fieldPath4 != null) fieldPaths.add(fieldPath4); + if (fieldPath5 != null) fieldPaths.add(fieldPath5); + if (fieldPath6 != null) fieldPaths.add(fieldPath6); + if (fieldPath7 != null) fieldPaths.add(fieldPath7); + if (fieldPath8 != null) fieldPaths.add(fieldPath8); + if (fieldPath9 != null) fieldPaths.add(fieldPath9); + if (fieldPath10 != null) fieldPaths.add(fieldPath10); + if (fieldPath11 != null) fieldPaths.add(fieldPath11); + if (fieldPath12 != null) fieldPaths.add(fieldPath12); + if (fieldPath13 != null) fieldPaths.add(fieldPath13); + if (fieldPath14 != null) fieldPaths.add(fieldPath14); + if (fieldPath15 != null) fieldPaths.add(fieldPath15); + if (fieldPath16 != null) fieldPaths.add(fieldPath16); + if (fieldPath17 != null) fieldPaths.add(fieldPath17); + if (fieldPath18 != null) fieldPaths.add(fieldPath18); + if (fieldPath19 != null) fieldPaths.add(fieldPath19); + if (fieldPath20 != null) fieldPaths.add(fieldPath20); + if (fieldPath21 != null) fieldPaths.add(fieldPath21); + if (fieldPath22 != null) fieldPaths.add(fieldPath22); + if (fieldPath23 != null) fieldPaths.add(fieldPath23); + if (fieldPath24 != null) fieldPaths.add(fieldPath24); + if (fieldPath25 != null) fieldPaths.add(fieldPath25); + if (fieldPath26 != null) fieldPaths.add(fieldPath26); + if (fieldPath27 != null) fieldPaths.add(fieldPath27); + if (fieldPath28 != null) fieldPaths.add(fieldPath28); + if (fieldPath29 != null) fieldPaths.add(fieldPath29); + if (fieldPath30 != null) fieldPaths.add(fieldPath30); + + return Pipeline._(_firestore, [ + ..._stages, + _RemoveFieldsStage(fieldPaths), + ]); + } + + /// Replaces documents with the result of an expression + Pipeline replaceWith(PipelineExpression expression) { + return Pipeline._(_firestore, [ + ..._stages, + _ReplaceWithStage(expression), + ]); + } + + /// Samples documents using a sampling strategy + Pipeline sample(PipelineSample sample) { + return Pipeline._(_firestore, [ + ..._stages, + _SampleStage(sample), + ]); + } + + /// Selects specific fields using expressions + Pipeline select( + PipelineExpression expression1, [ + PipelineExpression? expression2, + PipelineExpression? expression3, + PipelineExpression? expression4, + PipelineExpression? expression5, + PipelineExpression? expression6, + PipelineExpression? expression7, + PipelineExpression? expression8, + PipelineExpression? expression9, + PipelineExpression? expression10, + PipelineExpression? expression11, + PipelineExpression? expression12, + PipelineExpression? expression13, + PipelineExpression? expression14, + PipelineExpression? expression15, + PipelineExpression? expression16, + PipelineExpression? expression17, + PipelineExpression? expression18, + PipelineExpression? expression19, + PipelineExpression? expression20, + PipelineExpression? expression21, + PipelineExpression? expression22, + PipelineExpression? expression23, + PipelineExpression? expression24, + PipelineExpression? expression25, + PipelineExpression? expression26, + PipelineExpression? expression27, + PipelineExpression? expression28, + PipelineExpression? expression29, + PipelineExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + + return Pipeline._(_firestore, [ + ..._stages, + _SelectStage(expressions), + ]); + } + + /// Sorts results using an ordering specification + Pipeline sort(Ordering ordering) { + return Pipeline._(_firestore, [ + ..._stages, + _SortStage(ordering), + ]); + } + + /// Unnests arrays into separate documents + Pipeline unnest(PipelineExpression expression, [String? indexField]) { + return Pipeline._(_firestore, [ + ..._stages, + _UnnestStage(expression, indexField), + ]); + } + + /// Unions results with another pipeline + Pipeline union(Pipeline pipeline) { + return Pipeline._(_firestore, [ + ..._stages, + _UnionStage(pipeline), + ]); + } + + /// Filters documents using a boolean expression + Pipeline where(BooleanExpression expression) { + return Pipeline._(_firestore, [ + ..._stages, + _WhereStage(expression), + ]); + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart new file mode 100644 index 000000000000..1dd2fff39d52 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart @@ -0,0 +1,58 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Base class for aggregate functions used in pipelines +abstract class PipelineAggregateFunction implements PipelineSerializable { + String? _alias; + + /// Assigns an alias to this aggregate function + PipelineAggregateFunction as(String alias) { + _alias = alias; + return this; + } + + String? get alias => _alias; + + String get name; + + @override + Map toMap() { + final map = { + 'name': name, + }; + if (_alias != null) { + map['alias'] = _alias; + } + return map; + } +} + +/// Counts all documents in the pipeline result +class CountAll extends PipelineAggregateFunction { + CountAll(); + + @override + String get name => 'count_all'; +} + +/// Counts non-null values of the specified expression +class Count extends PipelineAggregateFunction { + final PipelineExpression expression; + + Count(this.expression); + + @override + String get name => 'count'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_distance.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_distance.dart new file mode 100644 index 000000000000..8f01b16de52e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_distance.dart @@ -0,0 +1,17 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Distance measure algorithms for vector similarity search +enum DistanceMeasure { + /// Cosine similarity + cosine, + + /// Euclidean distance + euclidean, + + /// Dot product + dotProduct, +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart new file mode 100644 index 000000000000..415764350786 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart @@ -0,0 +1,394 @@ +// Copyright 2020, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Base interface for pipeline serialization +abstract class PipelineSerializable { + Map toMap(); +} + +/// Base class for all pipeline expressions +abstract class PipelineExpression implements PipelineSerializable { + String? _alias; + + /// Assigns an alias to this expression + PipelineExpression as(String alias) { + _alias = alias; + return this; + } + + /// Creates a descending ordering for this expression + Ordering descending() { + return Ordering(this, OrderDirection.desc); + } + + /// Creates an ascending ordering for this expression + Ordering ascending() { + return Ordering(this, OrderDirection.asc); + } + + String? get alias => _alias; + + String get name; + + @override + Map toMap() { + final map = { + 'name': name, + }; + if (_alias != null) { + map['alias'] = _alias; + } + return map; + } +} + +/// Base class for function expressions +abstract class FunctionExpression extends PipelineExpression {} + +/// Represents a field reference in a pipeline expression +class Field extends PipelineExpression { + final String fieldName; + + Field(this.fieldName); + + @override + String get name => 'field'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'field': fieldName, + }; + return map; + } +} + +/// Represents a constant literal value in a pipeline expression +class Constant extends PipelineExpression { + final dynamic literal; + + Constant(this.literal); + + @override + String get name => 'constant'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'literal': literal, + }; + return map; + } +} + +/// Represents a concatenation function expression +class Concat extends FunctionExpression { + final List expressions; + + Concat(this.expressions); + + @override + String get name => 'concat'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }; + return map; + } +} + +/// Represents an aliased expression wrapper +class AliasedExpression extends PipelineExpression { + final PipelineExpression expression; + + AliasedExpression(this.expression); + + @override + String get name => 'alias'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Base class for boolean expressions used in filtering +abstract class BooleanExpression extends PipelineExpression {} + +/// Represents a filter expression for pipeline where clauses +class PipelineFilter extends BooleanExpression { + final Object field; + final Object? isEqualTo; + final Object? isNotEqualTo; + final Object? isLessThan; + final Object? isLessThanOrEqualTo; + final Object? isGreaterThan; + final Object? isGreaterThanOrEqualTo; + final Object? arrayContains; + final List? arrayContainsAny; + final List? whereIn; + final List? whereNotIn; + final bool? isNull; + final bool? isNotNull; + final BooleanExpression? _andExpression; + final BooleanExpression? _orExpression; + + PipelineFilter( + this.field, { + this.isEqualTo, + this.isNotEqualTo, + this.isLessThan, + this.isLessThanOrEqualTo, + this.isGreaterThan, + this.isGreaterThanOrEqualTo, + this.arrayContains, + this.arrayContainsAny, + this.whereIn, + this.whereNotIn, + this.isNull, + this.isNotNull, + }) : _andExpression = null, + _orExpression = null; + + PipelineFilter._internal({ + required BooleanExpression? andExpression, + required BooleanExpression? orExpression, + }) : field = '', + isEqualTo = null, + isNotEqualTo = null, + isLessThan = null, + isLessThanOrEqualTo = null, + isGreaterThan = null, + isGreaterThanOrEqualTo = null, + arrayContains = null, + arrayContainsAny = null, + whereIn = null, + whereNotIn = null, + isNull = null, + isNotNull = null, + _andExpression = andExpression, + _orExpression = orExpression; + + /// Creates an OR filter combining multiple boolean expressions + static PipelineFilter or( + BooleanExpression expression1, [ + BooleanExpression? expression2, + BooleanExpression? expression3, + BooleanExpression? expression4, + BooleanExpression? expression5, + BooleanExpression? expression6, + BooleanExpression? expression7, + BooleanExpression? expression8, + BooleanExpression? expression9, + BooleanExpression? expression10, + BooleanExpression? expression11, + BooleanExpression? expression12, + BooleanExpression? expression13, + BooleanExpression? expression14, + BooleanExpression? expression15, + BooleanExpression? expression16, + BooleanExpression? expression17, + BooleanExpression? expression18, + BooleanExpression? expression19, + BooleanExpression? expression20, + BooleanExpression? expression21, + BooleanExpression? expression22, + BooleanExpression? expression23, + BooleanExpression? expression24, + BooleanExpression? expression25, + BooleanExpression? expression26, + BooleanExpression? expression27, + BooleanExpression? expression28, + BooleanExpression? expression29, + BooleanExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + + return PipelineFilter._internal( + orExpression: _combineExpressions(expressions, 'or'), + andExpression: null, + ); + } + + /// Creates an AND filter combining multiple boolean expressions + static PipelineFilter and( + BooleanExpression expression1, [ + BooleanExpression? expression2, + BooleanExpression? expression3, + BooleanExpression? expression4, + BooleanExpression? expression5, + BooleanExpression? expression6, + BooleanExpression? expression7, + BooleanExpression? expression8, + BooleanExpression? expression9, + BooleanExpression? expression10, + BooleanExpression? expression11, + BooleanExpression? expression12, + BooleanExpression? expression13, + BooleanExpression? expression14, + BooleanExpression? expression15, + BooleanExpression? expression16, + BooleanExpression? expression17, + BooleanExpression? expression18, + BooleanExpression? expression19, + BooleanExpression? expression20, + BooleanExpression? expression21, + BooleanExpression? expression22, + BooleanExpression? expression23, + BooleanExpression? expression24, + BooleanExpression? expression25, + BooleanExpression? expression26, + BooleanExpression? expression27, + BooleanExpression? expression28, + BooleanExpression? expression29, + BooleanExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + + return PipelineFilter._internal( + andExpression: _combineExpressions(expressions, 'and'), + orExpression: null, + ); + } + + static BooleanExpression _combineExpressions( + List expressions, + String operator, + ) { + if (expressions.length == 1) return expressions.first; + + // Create a nested structure for multiple expressions + BooleanExpression result = expressions.first; + for (int i = 1; i < expressions.length; i++) { + if (operator == 'and') { + result = PipelineFilter.and(result, expressions[i]); + } else { + result = PipelineFilter.or(result, expressions[i]); + } + } + return result; + } + + @override + String get name => 'filter'; + + @override + Map toMap() { + final map = super.toMap(); + + if (_andExpression != null) { + map['args'] = { + 'operator': 'and', + 'expressions': [_andExpression.toMap()], + }; + return map; + } + + if (_orExpression != null) { + map['args'] = { + 'operator': 'or', + 'expressions': [_orExpression.toMap()], + }; + return map; + } + + final args = {}; + if (field is String) { + args['field'] = field; + } else if (field is Field) { + args['field'] = (field as Field).fieldName; + } + + if (isEqualTo != null) args['isEqualTo'] = isEqualTo; + if (isNotEqualTo != null) args['isNotEqualTo'] = isNotEqualTo; + if (isLessThan != null) args['isLessThan'] = isLessThan; + if (isLessThanOrEqualTo != null) { + args['isLessThanOrEqualTo'] = isLessThanOrEqualTo; + } + if (isGreaterThan != null) args['isGreaterThan'] = isGreaterThan; + if (isGreaterThanOrEqualTo != null) { + args['isGreaterThanOrEqualTo'] = isGreaterThanOrEqualTo; + } + if (arrayContains != null) args['arrayContains'] = arrayContains; + if (arrayContainsAny != null) { + args['arrayContainsAny'] = arrayContainsAny; + } + if (whereIn != null) args['whereIn'] = whereIn; + if (whereNotIn != null) args['whereNotIn'] = whereNotIn; + if (isNull != null) args['isNull'] = isNull; + if (isNotNull != null) args['isNotNull'] = isNotNull; + + map['args'] = args; + return map; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart new file mode 100644 index 000000000000..b9832c32a105 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart @@ -0,0 +1,30 @@ +// Copyright 2020, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Direction for ordering results +enum OrderDirection { + /// Ascending order + asc, + + /// Descending order + desc, +} + +/// Represents an ordering specification for pipeline sorting +class Ordering implements PipelineSerializable { + final PipelineExpression expression; + final OrderDirection direction; + + Ordering(this.expression, this.direction); + + @override + Map toMap() { + return { + 'expression': expression.toMap(), + 'order_direction': direction == OrderDirection.asc ? 'asc' : 'desc', + }; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_sample.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_sample.dart new file mode 100644 index 000000000000..4136c9922872 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_sample.dart @@ -0,0 +1,43 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Base class for pipeline sampling strategies +abstract class PipelineSample implements PipelineSerializable { + const PipelineSample(); + + /// Creates a sample with a fixed size + factory PipelineSample.withSize(int size) = _PipelineSampleSize; + + /// Creates a sample with a percentage + factory PipelineSample.withPercentage(double percentage) = + _PipelineSamplePercentage; +} + +/// Sample stage with a fixed size +class _PipelineSampleSize extends PipelineSample { + final int size; + + const _PipelineSampleSize(this.size); + + @override + Map toMap() => { + 'type': 'size', + 'value': size, + }; +} + +/// Sample stage with a percentage +class _PipelineSamplePercentage extends PipelineSample { + final double percentage; + + const _PipelineSamplePercentage(this.percentage); + + @override + Map toMap() => { + 'type': 'percentage', + 'value': percentage, + }; +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart new file mode 100644 index 000000000000..12e4f1ba6cb7 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart @@ -0,0 +1,66 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Provides methods to create pipelines from different sources +class PipelineSource { + final FirebaseFirestore _firestore; + + PipelineSource._(this._firestore); + + /// Creates a pipeline from a collection path + Pipeline collection(String collectionPath) { + if (collectionPath.isEmpty) { + throw ArgumentError('A collection path must be a non-empty string.'); + } else if (collectionPath.contains('//')) { + throw ArgumentError('A collection path must not contain "//".'); + } + + return Pipeline._(_firestore, [ + _CollectionPipelineStage(collectionPath), + ]); + } + + /// Creates a pipeline from a collection reference + Pipeline collectionReference( + CollectionReference> collectionReference) { + return Pipeline._(_firestore, [ + _CollectionPipelineStage(collectionReference.path), + ]); + } + + /// Creates a pipeline from a collection group + Pipeline collectionGroup(String collectionId) { + if (collectionId.isEmpty) { + throw ArgumentError('A collection ID must be a non-empty string.'); + } else if (collectionId.contains('/')) { + throw ArgumentError( + 'A collection ID passed to collectionGroup() cannot contain "/".', + ); + } + + return Pipeline._(_firestore, [ + _CollectionGroupPipelineStage(collectionId), + ]); + } + + /// Creates a pipeline from a list of document references + Pipeline documents(List>> documents) { + if (documents.isEmpty) { + throw ArgumentError('Documents list must not be empty.'); + } + + return Pipeline._(_firestore, [ + _DocumentsPipelineStage(documents), + ]); + } + + /// Creates a pipeline from the entire database + Pipeline database() { + return Pipeline._(_firestore, [ + _DatabasePipelineStage(), + ]); + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart new file mode 100644 index 000000000000..9207533abbe8 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart @@ -0,0 +1,387 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Base sealed class for all pipeline stages +sealed class PipelineStage implements PipelineSerializable { + String get name; +} + +/// Stage representing a collection source +final class _CollectionPipelineStage extends PipelineStage { + final String collectionPath; + + _CollectionPipelineStage(this.collectionPath); + + @override + String get name => 'collection'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'path': collectionPath, + }, + }; + } +} + +/// Stage representing a documents source +final class _DocumentsPipelineStage extends PipelineStage { + final List>> documents; + + _DocumentsPipelineStage(this.documents); + + @override + String get name => 'documents'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': documents + .map((doc) => { + 'path': doc.path, + }) + .toList(), + }; + } +} + +/// Stage representing a database source +final class _DatabasePipelineStage extends PipelineStage { + _DatabasePipelineStage(); + + @override + String get name => 'database'; + + @override + Map toMap() { + return { + 'stage': name, + }; + } +} + +/// Stage representing a collection group source +final class _CollectionGroupPipelineStage extends PipelineStage { + final String collectionPath; + + _CollectionGroupPipelineStage(this.collectionPath); + + @override + String get name => 'collection_group'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'path': collectionPath, + }, + }; + } +} + +/// Stage for adding fields to documents +final class _AddFieldsStage extends PipelineStage { + final List expressions; + + _AddFieldsStage(this.expressions); + + @override + String get name => 'add_fields'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Stage for aggregating data +final class _AggregateStage extends PipelineStage { + final List aggregateFunctions; + + _AggregateStage(this.aggregateFunctions); + + @override + String get name => 'aggregate'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'aggregate_functions': + aggregateFunctions.map((func) => func.toMap()).toList(), + }, + }; + } +} + +/// Stage for getting distinct values +final class _DistinctStage extends PipelineStage { + final List expressions; + + _DistinctStage(this.expressions); + + @override + String get name => 'distinct'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Stage for finding nearest vectors +final class _FindNearestStage extends PipelineStage { + final Field vectorField; + final List vectorValue; + final DistanceMeasure distanceMeasure; + final int? limit; + + _FindNearestStage( + this.vectorField, + this.vectorValue, + this.distanceMeasure, { + this.limit, + }); + + @override + String get name => 'find_nearest'; + + @override + Map toMap() { + final map = { + 'stage': name, + 'args': { + 'vector_field': vectorField.fieldName, + 'vector_value': vectorValue, + 'distance_measure': distanceMeasure.name, + }, + }; + if (limit != null) { + map['args']['limit'] = limit; + } + return map; + } +} + +/// Stage for limiting results +final class _LimitStage extends PipelineStage { + final int limit; + + _LimitStage(this.limit); + + @override + String get name => 'limit'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'limit': limit, + }, + }; + } +} + +/// Stage for offsetting results +final class _OffsetStage extends PipelineStage { + final int offset; + + _OffsetStage(this.offset); + + @override + String get name => 'offset'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'offset': offset, + }, + }; + } +} + +/// Stage for removing fields +final class _RemoveFieldsStage extends PipelineStage { + final List fieldPaths; + + _RemoveFieldsStage(this.fieldPaths); + + @override + String get name => 'remove_fields'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'field_paths': fieldPaths, + }, + }; + } +} + +/// Stage for replacing documents +final class _ReplaceWithStage extends PipelineStage { + final PipelineExpression expression; + + _ReplaceWithStage(this.expression); + + @override + String get name => 'replace_with'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Stage for sampling documents +final class _SampleStage extends PipelineStage { + final PipelineSample sample; + + _SampleStage(this.sample); + + @override + String get name => 'sample'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': sample.toMap(), + }; + } +} + +/// Stage for selecting specific fields +final class _SelectStage extends PipelineStage { + final List expressions; + + _SelectStage(this.expressions); + + @override + String get name => 'select'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Stage for sorting results +final class _SortStage extends PipelineStage { + final Ordering ordering; + + _SortStage(this.ordering); + + @override + String get name => 'sort'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expression': ordering.expression.toMap(), + 'order_direction': + ordering.direction == OrderDirection.asc ? 'asc' : 'desc', + }, + }; + } +} + +/// Stage for unnesting arrays +final class _UnnestStage extends PipelineStage { + final PipelineExpression expression; + final String? indexField; + + _UnnestStage(this.expression, this.indexField); + + @override + String get name => 'unnest'; + + @override + Map toMap() { + final map = { + 'stage': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + if (indexField != null) { + map['args']['index_field'] = indexField; + } + return map; + } +} + +/// Stage for union with another pipeline +final class _UnionStage extends PipelineStage { + final Pipeline pipeline; + + _UnionStage(this.pipeline); + + @override + String get name => 'union'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'pipeline': pipeline.getSerializableStages(), + }, + }; + } +} + +/// Stage for filtering documents +final class _WhereStage extends PipelineStage { + final BooleanExpression expression; + + _WhereStage(this.expression); + + @override + String get name => 'where'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart index 9f9b8e7866e0..58a894053a76 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart @@ -29,6 +29,7 @@ export 'src/platform_interface/platform_interface_index_definitions.dart'; export 'src/platform_interface/platform_interface_load_bundle_task.dart'; export 'src/platform_interface/platform_interface_load_bundle_task_snapshot.dart'; export 'src/platform_interface/platform_interface_persistent_cache_index_manager.dart'; +export 'src/platform_interface/platform_interface_pipeline_snapshot.dart'; export 'src/platform_interface/platform_interface_query.dart'; export 'src/platform_interface/platform_interface_query_snapshot.dart'; export 'src/platform_interface/platform_interface_transaction.dart'; diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart index 3faffc0a3778..1e76c5825670 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart @@ -243,6 +243,14 @@ abstract class FirebaseFirestorePlatform extends PlatformInterface { throw UnimplementedError('setLoggingEnabled() is not implemented'); } + /// Executes a pipeline and returns the results. + /// + /// The [stages] parameter contains the serialized pipeline stages. + Future executePipeline( + List> stages) { + throw UnimplementedError('executePipeline() is not implemented'); + } + @override //ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) => diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline_snapshot.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline_snapshot.dart new file mode 100644 index 000000000000..8b8d3b6fda30 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline_snapshot.dart @@ -0,0 +1,40 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import '../../cloud_firestore_platform_interface.dart'; +import 'platform_interface_document_reference.dart'; + +/// Platform interface for [PipelineSnapshot]. +abstract class PipelineSnapshotPlatform extends PlatformInterface { + /// Create an instance of [PipelineSnapshotPlatform]. + PipelineSnapshotPlatform() : super(token: _token); + + static final Object _token = Object(); + + /// The results of the pipeline execution + List get results; + + /// The execution time of the pipeline + DateTime get executionTime; +} + +/// Platform interface for [PipelineResult]. +abstract class PipelineResultPlatform extends PlatformInterface { + /// Create an instance of [PipelineResultPlatform]. + PipelineResultPlatform() : super(token: _token); + + static final Object _token = Object(); + + /// The document reference + DocumentReferencePlatform get document; + + /// The creation time of the document + DateTime get createTime; + + /// The update time of the document + DateTime get updateTime; +} From 2de48729dce0bc82177f6e02c7d83ac9ec9cb1fb Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Wed, 11 Feb 2026 15:06:06 +0000 Subject: [PATCH 2/5] feat(firestore): implement pipeline execution and stages with options --- .../cloud_firestore/lib/cloud_firestore.dart | 1 + .../cloud_firestore/lib/src/pipeline.dart | 356 +++++++++--------- .../lib/src/pipeline_aggregate.dart | 2 +- .../lib/src/pipeline_execute_options.dart | 20 + .../lib/src/pipeline_expression.dart | 121 +++--- .../lib/src/pipeline_ordering.dart | 4 +- .../lib/src/pipeline_source.dart | 30 +- .../lib/src/pipeline_stage.dart | 12 +- .../cloud_firestore_platform_interface.dart | 1 + .../method_channel_firestore.dart | 31 ++ .../method_channel_pipeline.dart | 51 +++ .../method_channel_pipeline_snapshot.dart | 69 ++++ .../platform_interface_firestore.dart | 9 +- .../platform_interface_pipeline.dart | 54 +++ 14 files changed, 516 insertions(+), 245 deletions(-) create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_execute_options.dart create mode 100644 packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline.dart create mode 100644 packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart create mode 100644 packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline.dart diff --git a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart index c84108ac3686..b0febde386b2 100755 --- a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart @@ -58,6 +58,7 @@ part 'src/persistent_cache_index_manager.dart'; part 'src/pipeline.dart'; part 'src/pipeline_aggregate.dart'; part 'src/pipeline_distance.dart'; +part 'src/pipeline_execute_options.dart'; part 'src/pipeline_expression.dart'; part 'src/pipeline_ordering.dart'; part 'src/pipeline_sample.dart'; diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart index e7849f43afd7..956685e3e8a7 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart @@ -6,15 +6,31 @@ part of '../cloud_firestore.dart'; /// A pipeline for querying and transforming Firestore data class Pipeline { - final List _stages; final FirebaseFirestore _firestore; + final PipelinePlatform _delegate; - Pipeline._(this._firestore, this._stages); + Pipeline._(this._firestore, this._delegate) { + PipelinePlatform.verify(_delegate); + } + + /// Exposes the [stages] on the pipeline delegate. + /// + /// This should only be used for testing to ensure that all + /// pipeline stages are correctly set on the underlying delegate + /// when being tested from a different package. + @visibleForTesting + List> get stages { + return _delegate.stages; + } /// Executes the pipeline and returns a snapshot of the results - Future execute() async { - final platformSnapshot = - await _firestore._delegate.executePipeline(_toSerializableStages()); + Future execute({ExecuteOptions? options}) async { + final optionsMap = options != null + ? { + 'indexMode': options.indexMode.name, + } + : null; + final platformSnapshot = await _delegate.execute(options: optionsMap); return _convertPlatformSnapshot(platformSnapshot); } @@ -35,52 +51,42 @@ class Pipeline { return PipelineSnapshot._(results, platformSnapshot.executionTime); } - /// Converts stages to serializable format for platform communication - List> _toSerializableStages() { - return _stages.map((stage) => stage.toMap()).toList(); - } - - /// Public method to get serializable stages (used by union stage) - List> getSerializableStages() { - return _toSerializableStages(); - } - // Pipeline Actions /// Adds fields to documents using expressions Pipeline addFields( - PipelineExpression expression1, [ - PipelineExpression? expression2, - PipelineExpression? expression3, - PipelineExpression? expression4, - PipelineExpression? expression5, - PipelineExpression? expression6, - PipelineExpression? expression7, - PipelineExpression? expression8, - PipelineExpression? expression9, - PipelineExpression? expression10, - PipelineExpression? expression11, - PipelineExpression? expression12, - PipelineExpression? expression13, - PipelineExpression? expression14, - PipelineExpression? expression15, - PipelineExpression? expression16, - PipelineExpression? expression17, - PipelineExpression? expression18, - PipelineExpression? expression19, - PipelineExpression? expression20, - PipelineExpression? expression21, - PipelineExpression? expression22, - PipelineExpression? expression23, - PipelineExpression? expression24, - PipelineExpression? expression25, - PipelineExpression? expression26, - PipelineExpression? expression27, - PipelineExpression? expression28, - PipelineExpression? expression29, - PipelineExpression? expression30, + Expression expression1, [ + Expression? expression2, + Expression? expression3, + Expression? expression4, + Expression? expression5, + Expression? expression6, + Expression? expression7, + Expression? expression8, + Expression? expression9, + Expression? expression10, + Expression? expression11, + Expression? expression12, + Expression? expression13, + Expression? expression14, + Expression? expression15, + Expression? expression16, + Expression? expression17, + Expression? expression18, + Expression? expression19, + Expression? expression20, + Expression? expression21, + Expression? expression22, + Expression? expression23, + Expression? expression24, + Expression? expression25, + Expression? expression26, + Expression? expression27, + Expression? expression28, + Expression? expression29, + Expression? expression30, ]) { - final expressions = [expression1]; + final expressions = [expression1]; if (expression2 != null) expressions.add(expression2); if (expression3 != null) expressions.add(expression3); if (expression4 != null) expressions.add(expression4); @@ -111,10 +117,11 @@ class Pipeline { if (expression29 != null) expressions.add(expression29); if (expression30 != null) expressions.add(expression30); - return Pipeline._(_firestore, [ - ..._stages, - _AddFieldsStage(expressions), - ]); + final stage = _AddFieldsStage(expressions); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Aggregates data using aggregate functions @@ -181,46 +188,47 @@ class Pipeline { if (aggregateFunction29 != null) functions.add(aggregateFunction29); if (aggregateFunction30 != null) functions.add(aggregateFunction30); - return Pipeline._(_firestore, [ - ..._stages, - _AggregateStage(functions), - ]); + final stage = _AggregateStage(functions); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Gets distinct values based on expressions Pipeline distinct( - PipelineExpression expression1, [ - PipelineExpression? expression2, - PipelineExpression? expression3, - PipelineExpression? expression4, - PipelineExpression? expression5, - PipelineExpression? expression6, - PipelineExpression? expression7, - PipelineExpression? expression8, - PipelineExpression? expression9, - PipelineExpression? expression10, - PipelineExpression? expression11, - PipelineExpression? expression12, - PipelineExpression? expression13, - PipelineExpression? expression14, - PipelineExpression? expression15, - PipelineExpression? expression16, - PipelineExpression? expression17, - PipelineExpression? expression18, - PipelineExpression? expression19, - PipelineExpression? expression20, - PipelineExpression? expression21, - PipelineExpression? expression22, - PipelineExpression? expression23, - PipelineExpression? expression24, - PipelineExpression? expression25, - PipelineExpression? expression26, - PipelineExpression? expression27, - PipelineExpression? expression28, - PipelineExpression? expression29, - PipelineExpression? expression30, + Expression expression1, [ + Expression? expression2, + Expression? expression3, + Expression? expression4, + Expression? expression5, + Expression? expression6, + Expression? expression7, + Expression? expression8, + Expression? expression9, + Expression? expression10, + Expression? expression11, + Expression? expression12, + Expression? expression13, + Expression? expression14, + Expression? expression15, + Expression? expression16, + Expression? expression17, + Expression? expression18, + Expression? expression19, + Expression? expression20, + Expression? expression21, + Expression? expression22, + Expression? expression23, + Expression? expression24, + Expression? expression25, + Expression? expression26, + Expression? expression27, + Expression? expression28, + Expression? expression29, + Expression? expression30, ]) { - final expressions = [expression1]; + final expressions = [expression1]; if (expression2 != null) expressions.add(expression2); if (expression3 != null) expressions.add(expression3); if (expression4 != null) expressions.add(expression4); @@ -251,10 +259,11 @@ class Pipeline { if (expression29 != null) expressions.add(expression29); if (expression30 != null) expressions.add(expression30); - return Pipeline._(_firestore, [ - ..._stages, - _DistinctStage(expressions), - ]); + final stage = _DistinctStage(expressions); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Finds nearest vectors using vector similarity search @@ -264,27 +273,30 @@ class Pipeline { DistanceMeasure distanceMeasure, { int? limit, }) { - return Pipeline._(_firestore, [ - ..._stages, - _FindNearestStage(vectorField, vectorValue, distanceMeasure, - limit: limit), - ]); + final stage = _FindNearestStage(vectorField, vectorValue, distanceMeasure, + limit: limit); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Limits the number of results Pipeline limit(int limit) { - return Pipeline._(_firestore, [ - ..._stages, - _LimitStage(limit), - ]); + final stage = _LimitStage(limit); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Offsets the results Pipeline offset(int offset) { - return Pipeline._(_firestore, [ - ..._stages, - _OffsetStage(offset), - ]); + final stage = _OffsetStage(offset); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Removes specified fields from documents @@ -351,62 +363,65 @@ class Pipeline { if (fieldPath29 != null) fieldPaths.add(fieldPath29); if (fieldPath30 != null) fieldPaths.add(fieldPath30); - return Pipeline._(_firestore, [ - ..._stages, - _RemoveFieldsStage(fieldPaths), - ]); + final stage = _RemoveFieldsStage(fieldPaths); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Replaces documents with the result of an expression - Pipeline replaceWith(PipelineExpression expression) { - return Pipeline._(_firestore, [ - ..._stages, - _ReplaceWithStage(expression), - ]); + Pipeline replaceWith(Expression expression) { + final stage = _ReplaceWithStage(expression); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Samples documents using a sampling strategy Pipeline sample(PipelineSample sample) { - return Pipeline._(_firestore, [ - ..._stages, - _SampleStage(sample), - ]); + final stage = _SampleStage(sample); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } - /// Selects specific fields using expressions + /// Selects specific fields using selectable expressions Pipeline select( - PipelineExpression expression1, [ - PipelineExpression? expression2, - PipelineExpression? expression3, - PipelineExpression? expression4, - PipelineExpression? expression5, - PipelineExpression? expression6, - PipelineExpression? expression7, - PipelineExpression? expression8, - PipelineExpression? expression9, - PipelineExpression? expression10, - PipelineExpression? expression11, - PipelineExpression? expression12, - PipelineExpression? expression13, - PipelineExpression? expression14, - PipelineExpression? expression15, - PipelineExpression? expression16, - PipelineExpression? expression17, - PipelineExpression? expression18, - PipelineExpression? expression19, - PipelineExpression? expression20, - PipelineExpression? expression21, - PipelineExpression? expression22, - PipelineExpression? expression23, - PipelineExpression? expression24, - PipelineExpression? expression25, - PipelineExpression? expression26, - PipelineExpression? expression27, - PipelineExpression? expression28, - PipelineExpression? expression29, - PipelineExpression? expression30, + Selectable expression1, [ + Selectable? expression2, + Selectable? expression3, + Selectable? expression4, + Selectable? expression5, + Selectable? expression6, + Selectable? expression7, + Selectable? expression8, + Selectable? expression9, + Selectable? expression10, + Selectable? expression11, + Selectable? expression12, + Selectable? expression13, + Selectable? expression14, + Selectable? expression15, + Selectable? expression16, + Selectable? expression17, + Selectable? expression18, + Selectable? expression19, + Selectable? expression20, + Selectable? expression21, + Selectable? expression22, + Selectable? expression23, + Selectable? expression24, + Selectable? expression25, + Selectable? expression26, + Selectable? expression27, + Selectable? expression28, + Selectable? expression29, + Selectable? expression30, ]) { - final expressions = [expression1]; + final expressions = [expression1]; if (expression2 != null) expressions.add(expression2); if (expression3 != null) expressions.add(expression3); if (expression4 != null) expressions.add(expression4); @@ -437,41 +452,46 @@ class Pipeline { if (expression29 != null) expressions.add(expression29); if (expression30 != null) expressions.add(expression30); - return Pipeline._(_firestore, [ - ..._stages, - _SelectStage(expressions), - ]); + final stage = _SelectStage(expressions); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Sorts results using an ordering specification Pipeline sort(Ordering ordering) { - return Pipeline._(_firestore, [ - ..._stages, - _SortStage(ordering), - ]); + final stage = _SortStage(ordering); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Unnests arrays into separate documents - Pipeline unnest(PipelineExpression expression, [String? indexField]) { - return Pipeline._(_firestore, [ - ..._stages, - _UnnestStage(expression, indexField), - ]); + Pipeline unnest(Expression expression, [String? indexField]) { + final stage = _UnnestStage(expression, indexField); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Unions results with another pipeline Pipeline union(Pipeline pipeline) { - return Pipeline._(_firestore, [ - ..._stages, - _UnionStage(pipeline), - ]); + final stage = _UnionStage(pipeline); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } /// Filters documents using a boolean expression Pipeline where(BooleanExpression expression) { - return Pipeline._(_firestore, [ - ..._stages, - _WhereStage(expression), - ]); + final stage = _WhereStage(expression); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); } } diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart index 1dd2fff39d52..f0946ac18995 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart @@ -40,7 +40,7 @@ class CountAll extends PipelineAggregateFunction { /// Counts non-null values of the specified expression class Count extends PipelineAggregateFunction { - final PipelineExpression expression; + final Expression expression; Count(this.expression); diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_execute_options.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_execute_options.dart new file mode 100644 index 000000000000..ee8b8e2eb42d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_execute_options.dart @@ -0,0 +1,20 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Index mode for pipeline execution +enum IndexMode { + /// Use recommended index mode + recommended, +} + +/// Options for executing a pipeline +class ExecuteOptions { + final IndexMode indexMode; + + const ExecuteOptions({ + this.indexMode = IndexMode.recommended, + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart index 415764350786..6323f23941fe 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart @@ -1,4 +1,4 @@ -// Copyright 2020, the Chromium project authors. Please see the AUTHORS file +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -10,13 +10,13 @@ abstract class PipelineSerializable { } /// Base class for all pipeline expressions -abstract class PipelineExpression implements PipelineSerializable { - String? _alias; - - /// Assigns an alias to this expression - PipelineExpression as(String alias) { - _alias = alias; - return this; +abstract class Expression implements PipelineSerializable { + /// Creates an aliased expression + AliasedExpression as(String alias) { + return AliasedExpression( + alias: alias, + expression: this, + ); } /// Creates a descending ordering for this expression @@ -29,27 +29,54 @@ abstract class PipelineExpression implements PipelineSerializable { return Ordering(this, OrderDirection.asc); } - String? get alias => _alias; - String get name; @override Map toMap() { - final map = { + return { 'name': name, }; - if (_alias != null) { - map['alias'] = _alias; - } - return map; } } /// Base class for function expressions -abstract class FunctionExpression extends PipelineExpression {} +abstract class FunctionExpression extends Expression {} + +/// Base class for selectable expressions (can be used in select stage) +abstract class Selectable extends Expression { + String get alias; + Expression get expression; +} + +/// Represents an aliased expression wrapper +class AliasedExpression extends Selectable { + @override + final String alias; + + @override + final Expression expression; + + AliasedExpression({ + required this.alias, + required this.expression, + }); + + @override + String get name => 'alias'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} /// Represents a field reference in a pipeline expression -class Field extends PipelineExpression { +class Field extends Selectable { final String fieldName; Field(this.fieldName); @@ -57,18 +84,25 @@ class Field extends PipelineExpression { @override String get name => 'field'; + @override + String get alias => fieldName; + + @override + Expression get expression => this; + @override Map toMap() { - final map = super.toMap(); - map['args'] = { - 'field': fieldName, + return { + 'name': name, + 'args': { + 'field': fieldName, + }, }; - return map; } } /// Represents a constant literal value in a pipeline expression -class Constant extends PipelineExpression { +class Constant extends Expression { final dynamic literal; Constant(this.literal); @@ -78,17 +112,18 @@ class Constant extends PipelineExpression { @override Map toMap() { - final map = super.toMap(); - map['args'] = { - 'literal': literal, + return { + 'name': name, + 'args': { + 'literal': literal, + }, }; - return map; } } /// Represents a concatenation function expression class Concat extends FunctionExpression { - final List expressions; + final List expressions; Concat(this.expressions); @@ -97,35 +132,17 @@ class Concat extends FunctionExpression { @override Map toMap() { - final map = super.toMap(); - map['args'] = { - 'expressions': expressions.map((expr) => expr.toMap()).toList(), - }; - return map; - } -} - -/// Represents an aliased expression wrapper -class AliasedExpression extends PipelineExpression { - final PipelineExpression expression; - - AliasedExpression(this.expression); - - @override - String get name => 'alias'; - - @override - Map toMap() { - final map = super.toMap(); - map['args'] = { - 'expression': expression.toMap(), + return { + 'name': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, }; - return map; } } /// Base class for boolean expressions used in filtering -abstract class BooleanExpression extends PipelineExpression {} +abstract class BooleanExpression extends Expression {} /// Represents a filter expression for pipeline where clauses class PipelineFilter extends BooleanExpression { @@ -246,8 +263,8 @@ class PipelineFilter extends BooleanExpression { if (expression30 != null) expressions.add(expression30); return PipelineFilter._internal( - orExpression: _combineExpressions(expressions, 'or'), andExpression: null, + orExpression: _combineExpressions(expressions, 'or'), ); } diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart index b9832c32a105..b55687fa5d8b 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart @@ -1,4 +1,4 @@ -// Copyright 2020, the Chromium project authors. Please see the AUTHORS file +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -15,7 +15,7 @@ enum OrderDirection { /// Represents an ordering specification for pipeline sorting class Ordering implements PipelineSerializable { - final PipelineExpression expression; + final Expression expression; final OrderDirection direction; Ordering(this.expression, this.direction); diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart index 12e4f1ba6cb7..c981d53cae0d 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart @@ -18,17 +18,17 @@ class PipelineSource { throw ArgumentError('A collection path must not contain "//".'); } - return Pipeline._(_firestore, [ - _CollectionPipelineStage(collectionPath), - ]); + final stage = _CollectionPipelineStage(collectionPath); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); } /// Creates a pipeline from a collection reference Pipeline collectionReference( CollectionReference> collectionReference) { - return Pipeline._(_firestore, [ - _CollectionPipelineStage(collectionReference.path), - ]); + final stage = _CollectionPipelineStage(collectionReference.path); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); } /// Creates a pipeline from a collection group @@ -41,9 +41,9 @@ class PipelineSource { ); } - return Pipeline._(_firestore, [ - _CollectionGroupPipelineStage(collectionId), - ]); + final stage = _CollectionGroupPipelineStage(collectionId); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); } /// Creates a pipeline from a list of document references @@ -52,15 +52,15 @@ class PipelineSource { throw ArgumentError('Documents list must not be empty.'); } - return Pipeline._(_firestore, [ - _DocumentsPipelineStage(documents), - ]); + final stage = _DocumentsPipelineStage(documents); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); } /// Creates a pipeline from the entire database Pipeline database() { - return Pipeline._(_firestore, [ - _DatabasePipelineStage(), - ]); + final stage = _DatabasePipelineStage(); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); } } diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart index 9207533abbe8..7532ddb8e544 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart @@ -88,7 +88,7 @@ final class _CollectionGroupPipelineStage extends PipelineStage { /// Stage for adding fields to documents final class _AddFieldsStage extends PipelineStage { - final List expressions; + final List expressions; _AddFieldsStage(this.expressions); @@ -129,7 +129,7 @@ final class _AggregateStage extends PipelineStage { /// Stage for getting distinct values final class _DistinctStage extends PipelineStage { - final List expressions; + final List expressions; _DistinctStage(this.expressions); @@ -243,7 +243,7 @@ final class _RemoveFieldsStage extends PipelineStage { /// Stage for replacing documents final class _ReplaceWithStage extends PipelineStage { - final PipelineExpression expression; + final Expression expression; _ReplaceWithStage(this.expression); @@ -281,7 +281,7 @@ final class _SampleStage extends PipelineStage { /// Stage for selecting specific fields final class _SelectStage extends PipelineStage { - final List expressions; + final List expressions; _SelectStage(this.expressions); @@ -323,7 +323,7 @@ final class _SortStage extends PipelineStage { /// Stage for unnesting arrays final class _UnnestStage extends PipelineStage { - final PipelineExpression expression; + final Expression expression; final String? indexField; _UnnestStage(this.expression, this.indexField); @@ -360,7 +360,7 @@ final class _UnionStage extends PipelineStage { return { 'stage': name, 'args': { - 'pipeline': pipeline.getSerializableStages(), + 'pipeline': pipeline.stages, }, }; } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart index 58a894053a76..2e7e97bec179 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart @@ -29,6 +29,7 @@ export 'src/platform_interface/platform_interface_index_definitions.dart'; export 'src/platform_interface/platform_interface_load_bundle_task.dart'; export 'src/platform_interface/platform_interface_load_bundle_task_snapshot.dart'; export 'src/platform_interface/platform_interface_persistent_cache_index_manager.dart'; +export 'src/platform_interface/platform_interface_pipeline.dart'; export 'src/platform_interface/platform_interface_pipeline_snapshot.dart'; export 'src/platform_interface/platform_interface_query.dart'; export 'src/platform_interface/platform_interface_query_snapshot.dart'; diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart index 573e5a3c91b9..73aacc45f2bb 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart @@ -15,6 +15,8 @@ import 'package:flutter/services.dart'; import 'method_channel_collection_reference.dart'; import 'method_channel_document_reference.dart'; +import 'method_channel_pipeline.dart'; +import 'method_channel_pipeline_snapshot.dart'; import 'method_channel_query.dart'; import 'method_channel_transaction.dart'; import 'method_channel_write_batch.dart'; @@ -350,4 +352,33 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { convertPlatformException(e, stack); } } + + @override + PipelinePlatform pipeline(List> initialStages) { + return MethodChannelPipeline(this, pigeonApp, stages: initialStages); + } + + @override + Future executePipeline( + List> stages, { + Map? options, + }) async { + try { + final MethodChannel channel = const MethodChannel( + 'plugins.flutter.io/firebase_firestore', + ); + final result = await channel.invokeMethod>( + 'Pipeline#execute', + { + 'app': pigeonApp, + 'stages': stages, + if (options != null) 'options': options, + }, + ); + + return MethodChannelPipelineSnapshot(this, pigeonApp, result!); + } on PlatformException catch (e, stack) { + throw convertPlatformException(e, stack); + } + } } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline.dart new file mode 100644 index 000000000000..7e0b65e43c7d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline.dart @@ -0,0 +1,51 @@ +// ignore_for_file: require_trailing_commas, unnecessary_lambdas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; +import 'package:cloud_firestore_platform_interface/src/platform_interface/platform_interface_pipeline.dart' + as pipeline; + +/// An implementation of [PipelinePlatform] that uses [MethodChannel] to +/// communicate with Firebase plugins. +class MethodChannelPipeline extends pipeline.PipelinePlatform { + /// Create a [MethodChannelPipeline] from [stages] + MethodChannelPipeline( + FirebaseFirestorePlatform _firestore, + this.pigeonApp, { + List>? stages, + }) : super(_firestore, stages); + + final FirestorePigeonFirebaseApp pigeonApp; + + /// Creates a new instance of [MethodChannelPipeline], however overrides + /// any existing [stages]. + /// + /// This is in place to ensure that changes to a pipeline don't mutate + /// other pipelines. + MethodChannelPipeline _copyWithStages(List> newStages) { + return MethodChannelPipeline( + firestore, + pigeonApp, + stages: List.unmodifiable([ + ...stages, + ...newStages, + ]), + ); + } + + @override + pipeline.PipelinePlatform addStage(Map serializedStage) { + return _copyWithStages([serializedStage]); + } + + @override + Future execute({ + Map? options, + }) async { + return firestore.executePipeline(stages, options: options); + } +} diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart new file mode 100644 index 000000000000..16cde78be465 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart @@ -0,0 +1,69 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; +import 'package:cloud_firestore_platform_interface/src/method_channel/method_channel_document_reference.dart'; + +/// An implementation of [PipelineSnapshotPlatform] that uses [MethodChannel] to +/// communicate with Firebase plugins. +class MethodChannelPipelineSnapshot extends PipelineSnapshotPlatform { + final List _results; + final DateTime _executionTime; + + /// Creates a [MethodChannelPipelineSnapshot] from the given [data] + MethodChannelPipelineSnapshot( + FirebaseFirestorePlatform firestore, + FirestorePigeonFirebaseApp pigeonApp, + Map data, + ) : _results = (data['results'] as List) + .map((result) => MethodChannelPipelineResult( + firestore, + pigeonApp, + result['document'] as String, + DateTime.fromMillisecondsSinceEpoch(result['createTime']), + DateTime.fromMillisecondsSinceEpoch(result['updateTime']), + )) + .toList(), + _executionTime = DateTime.fromMillisecondsSinceEpoch( + data['executionTime'] as int, + ), + super(); + + @override + List get results => _results; + + @override + DateTime get executionTime => _executionTime; +} + +/// An implementation of [PipelineResultPlatform] that uses [MethodChannel] to +/// communicate with Firebase plugins. +class MethodChannelPipelineResult extends PipelineResultPlatform { + final DocumentReferencePlatform _document; + final DateTime _createTime; + final DateTime _updateTime; + + MethodChannelPipelineResult( + FirebaseFirestorePlatform firestore, + FirestorePigeonFirebaseApp pigeonApp, + String documentPath, + this._createTime, + this._updateTime, + ) : _document = MethodChannelDocumentReference( + firestore, + documentPath, + pigeonApp, + ), + super(); + + @override + DocumentReferencePlatform get document => _document; + + @override + DateTime get createTime => _createTime; + + @override + DateTime get updateTime => _updateTime; +} diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart index 1e76c5825670..ee9cd3a32478 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart @@ -243,11 +243,18 @@ abstract class FirebaseFirestorePlatform extends PlatformInterface { throw UnimplementedError('setLoggingEnabled() is not implemented'); } + /// Creates a pipeline platform instance with initial stages. + PipelinePlatform pipeline(List> initialStages) { + throw UnimplementedError('pipeline() is not implemented'); + } + /// Executes a pipeline and returns the results. /// /// The [stages] parameter contains the serialized pipeline stages. Future executePipeline( - List> stages) { + List> stages, { + Map? options, + }) { throw UnimplementedError('executePipeline() is not implemented'); } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline.dart new file mode 100644 index 000000000000..2d0449ee4aef --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline.dart @@ -0,0 +1,54 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; +import 'package:meta/meta.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +/// Represents a pipeline for querying and transforming Firestore data. +@immutable +abstract class PipelinePlatform extends PlatformInterface { + /// Create a [PipelinePlatform] instance + PipelinePlatform(this.firestore, List>? stages) + : _stages = stages ?? [], + super(token: _token); + + static final Object _token = Object(); + + /// Throws an [AssertionError] if [instance] does not extend + /// [PipelinePlatform]. + /// + /// This is used by the app-facing [Pipeline] to ensure that + /// the object in which it's going to delegate calls has been + /// constructed properly. + static void verify(PipelinePlatform instance) { + PlatformInterface.verify(instance, _token); + } + + /// The [FirebaseFirestorePlatform] interface for this current pipeline. + final FirebaseFirestorePlatform firestore; + + /// Stores the pipeline stages. + final List> _stages; + + /// Exposes the [stages] on the pipeline delegate. + /// + /// This should only be used for testing to ensure that all + /// pipeline stages are correctly set on the underlying delegate + /// when being tested from a different package. + List> get stages { + return List.unmodifiable(_stages); + } + + /// Adds a serialized stage to the pipeline + PipelinePlatform addStage(Map serializedStage); + + /// Executes the pipeline and returns a snapshot of the results + Future execute({ + Map? options, + }); +} From ed55eedac4327f277adbeb09d4398161eddbb948 Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Thu, 12 Feb 2026 10:09:53 +0000 Subject: [PATCH 3/5] refactor: change PipelineSerializable to mixin and update Constant class properties --- .../cloud_firestore/lib/src/pipeline_expression.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart index 6323f23941fe..07d575168af5 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart @@ -5,7 +5,7 @@ part of '../cloud_firestore.dart'; /// Base interface for pipeline serialization -abstract class PipelineSerializable { +mixin PipelineSerializable { Map toMap(); } @@ -101,11 +101,11 @@ class Field extends Selectable { } } -/// Represents a constant literal value in a pipeline expression +/// Represents a constant value in a pipeline expression class Constant extends Expression { - final dynamic literal; + final Object value; - Constant(this.literal); + Constant(this.value); @override String get name => 'constant'; @@ -115,7 +115,7 @@ class Constant extends Expression { return { 'name': name, 'args': { - 'literal': literal, + 'value': value, }, }; } From 6f7ca832a762dd8f37387a9bc4e2606bd0c7e855 Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Thu, 12 Feb 2026 13:08:16 +0000 Subject: [PATCH 4/5] chore: add `Expression` functions --- .../lib/src/pipeline_expression.dart | 3118 +++++++++++++++-- 1 file changed, 2820 insertions(+), 298 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart index 07d575168af5..2c295e0f2e6f 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart @@ -9,6 +9,12 @@ mixin PipelineSerializable { Map toMap(); } +/// Helper function to convert values to Expression (wraps in Constant if needed) +Expression _toExpression(Object? value) { + if (value is Expression) return value; + return Constant(value!); +} + /// Base class for all pipeline expressions abstract class Expression implements PipelineSerializable { /// Creates an aliased expression @@ -29,280 +35,1485 @@ abstract class Expression implements PipelineSerializable { return Ordering(this, OrderDirection.asc); } - String get name; + // ============================================================================ + // CONDITIONAL / LOGIC OPERATIONS + // ============================================================================ - @override - Map toMap() { - return { - 'name': name, - }; + /// Returns an alternative expression if this expression is absent + Expression ifAbsent(Expression elseExpr) { + return _IfAbsentExpression(this, elseExpr); } -} -/// Base class for function expressions -abstract class FunctionExpression extends Expression {} + /// Returns an alternative value if this expression is absent + Expression ifAbsentValue(Object? elseValue) { + return _IfAbsentExpression(this, _toExpression(elseValue)); + } -/// Base class for selectable expressions (can be used in select stage) -abstract class Selectable extends Expression { - String get alias; - Expression get expression; -} + /// Returns an alternative expression if this expression errors + Expression ifError(Expression catchExpr) { + return _IfErrorExpression(this, catchExpr); + } -/// Represents an aliased expression wrapper -class AliasedExpression extends Selectable { - @override - final String alias; + /// Returns an alternative value if this expression errors + Expression ifErrorValue(Object? catchValue) { + return _IfErrorExpression(this, _toExpression(catchValue)); + } - @override - final Expression expression; + /// Checks if this expression is absent (null/undefined) + // ignore: use_to_and_as_if_applicable + BooleanExpression isAbsent() { + return _IsAbsentExpression(this); + } - AliasedExpression({ - required this.alias, - required this.expression, - }); + /// Checks if this expression produces an error + // ignore: use_to_and_as_if_applicable + BooleanExpression isError() { + return _IsErrorExpression(this); + } - @override - String get name => 'alias'; + /// Checks if this field expression exists in the document + // ignore: use_to_and_as_if_applicable + BooleanExpression exists() { + return _ExistsExpression(this); + } - @override - Map toMap() { - return { - 'name': name, - 'args': { - 'expression': expression.toMap(), - }, - }; + // ============================================================================ + // TYPE CONVERSION + // ============================================================================ + + /// Casts this expression to a boolean expression + BooleanExpression asBoolean() { + return _AsBooleanExpression(this); } -} -/// Represents a field reference in a pipeline expression -class Field extends Selectable { - final String fieldName; + /// Converts this expression to a string with a format + Expression toStringWithFormat(Expression format) { + return _ToStringWithFormatExpression(this, format); + } - Field(this.fieldName); + /// Converts this expression to a string with a literal format + Expression toStringWithFormatLiteral(String format) { + return _ToStringWithFormatExpression(this, Constant(format)); + } - @override - String get name => 'field'; + // ============================================================================ + // BITWISE OPERATIONS + // ============================================================================ - @override - String get alias => fieldName; + /// Performs bitwise AND with another expression + Expression bitAnd(Expression bitsOther) { + return _BitAndExpression(this, bitsOther); + } - @override - Expression get expression => this; + /// Performs bitwise AND with byte array + Expression bitAndBytes(List bitsOther) { + return _BitAndExpression(this, Constant(bitsOther)); + } - @override - Map toMap() { - return { - 'name': name, - 'args': { - 'field': fieldName, - }, - }; + /// Performs bitwise OR with another expression + Expression bitOr(Expression bitsOther) { + return _BitOrExpression(this, bitsOther); } -} -/// Represents a constant value in a pipeline expression -class Constant extends Expression { - final Object value; + /// Performs bitwise OR with byte array + Expression bitOrBytes(List bitsOther) { + return _BitOrExpression(this, Constant(bitsOther)); + } - Constant(this.value); + /// Performs bitwise XOR with another expression + Expression bitXor(Expression bitsOther) { + return _BitXorExpression(this, bitsOther); + } - @override - String get name => 'constant'; + /// Performs bitwise XOR with byte array + Expression bitXorBytes(List bitsOther) { + return _BitXorExpression(this, Constant(bitsOther)); + } - @override - Map toMap() { - return { - 'name': name, - 'args': { - 'value': value, - }, - }; + /// Performs bitwise NOT on this expression + // ignore: use_to_and_as_if_applicable + Expression bitNot() { + return _BitNotExpression(this); } -} -/// Represents a concatenation function expression -class Concat extends FunctionExpression { - final List expressions; + /// Shifts bits left by an expression amount + Expression bitLeftShift(Expression numberExpr) { + return _BitLeftShiftExpression(this, numberExpr); + } - Concat(this.expressions); + /// Shifts bits left by a literal amount + Expression bitLeftShiftLiteral(int number) { + return _BitLeftShiftExpression(this, Constant(number)); + } - @override - String get name => 'concat'; + /// Shifts bits right by an expression amount + Expression bitRightShift(Expression numberExpr) { + return _BitRightShiftExpression(this, numberExpr); + } - @override - Map toMap() { - return { - 'name': name, - 'args': { - 'expressions': expressions.map((expr) => expr.toMap()).toList(), - }, - }; + /// Shifts bits right by a literal amount + Expression bitRightShiftLiteral(int number) { + return _BitRightShiftExpression(this, Constant(number)); } -} -/// Base class for boolean expressions used in filtering -abstract class BooleanExpression extends Expression {} + // ============================================================================ + // DOCUMENT / PATH OPERATIONS + // ============================================================================ -/// Represents a filter expression for pipeline where clauses -class PipelineFilter extends BooleanExpression { - final Object field; - final Object? isEqualTo; - final Object? isNotEqualTo; - final Object? isLessThan; - final Object? isLessThanOrEqualTo; - final Object? isGreaterThan; - final Object? isGreaterThanOrEqualTo; - final Object? arrayContains; - final List? arrayContainsAny; - final List? whereIn; - final List? whereNotIn; - final bool? isNull; - final bool? isNotNull; - final BooleanExpression? _andExpression; - final BooleanExpression? _orExpression; + /// Returns the document ID from this path expression + // ignore: use_to_and_as_if_applicable + Expression documentId() { + return _DocumentIdExpression(this); + } - PipelineFilter( - this.field, { - this.isEqualTo, - this.isNotEqualTo, - this.isLessThan, - this.isLessThanOrEqualTo, - this.isGreaterThan, - this.isGreaterThanOrEqualTo, - this.arrayContains, - this.arrayContainsAny, - this.whereIn, - this.whereNotIn, - this.isNull, - this.isNotNull, - }) : _andExpression = null, - _orExpression = null; + /// Returns the collection ID from this path expression + // ignore: use_to_and_as_if_applicable + Expression collectionId() { + return _CollectionIdExpression(this); + } - PipelineFilter._internal({ - required BooleanExpression? andExpression, - required BooleanExpression? orExpression, - }) : field = '', - isEqualTo = null, - isNotEqualTo = null, - isLessThan = null, - isLessThanOrEqualTo = null, - isGreaterThan = null, - isGreaterThanOrEqualTo = null, - arrayContains = null, - arrayContainsAny = null, - whereIn = null, - whereNotIn = null, - isNull = null, - isNotNull = null, - _andExpression = andExpression, - _orExpression = orExpression; + // ============================================================================ + // MAP OPERATIONS + // ============================================================================ - /// Creates an OR filter combining multiple boolean expressions - static PipelineFilter or( - BooleanExpression expression1, [ - BooleanExpression? expression2, - BooleanExpression? expression3, - BooleanExpression? expression4, - BooleanExpression? expression5, - BooleanExpression? expression6, - BooleanExpression? expression7, - BooleanExpression? expression8, - BooleanExpression? expression9, - BooleanExpression? expression10, - BooleanExpression? expression11, - BooleanExpression? expression12, - BooleanExpression? expression13, - BooleanExpression? expression14, - BooleanExpression? expression15, - BooleanExpression? expression16, - BooleanExpression? expression17, - BooleanExpression? expression18, - BooleanExpression? expression19, - BooleanExpression? expression20, - BooleanExpression? expression21, - BooleanExpression? expression22, - BooleanExpression? expression23, - BooleanExpression? expression24, - BooleanExpression? expression25, - BooleanExpression? expression26, - BooleanExpression? expression27, - BooleanExpression? expression28, - BooleanExpression? expression29, - BooleanExpression? expression30, - ]) { - final expressions = [expression1]; - if (expression2 != null) expressions.add(expression2); - if (expression3 != null) expressions.add(expression3); - if (expression4 != null) expressions.add(expression4); - if (expression5 != null) expressions.add(expression5); - if (expression6 != null) expressions.add(expression6); - if (expression7 != null) expressions.add(expression7); - if (expression8 != null) expressions.add(expression8); - if (expression9 != null) expressions.add(expression9); - if (expression10 != null) expressions.add(expression10); - if (expression11 != null) expressions.add(expression11); - if (expression12 != null) expressions.add(expression12); - if (expression13 != null) expressions.add(expression13); - if (expression14 != null) expressions.add(expression14); - if (expression15 != null) expressions.add(expression15); - if (expression16 != null) expressions.add(expression16); - if (expression17 != null) expressions.add(expression17); - if (expression18 != null) expressions.add(expression18); - if (expression19 != null) expressions.add(expression19); - if (expression20 != null) expressions.add(expression20); - if (expression21 != null) expressions.add(expression21); - if (expression22 != null) expressions.add(expression22); - if (expression23 != null) expressions.add(expression23); - if (expression24 != null) expressions.add(expression24); - if (expression25 != null) expressions.add(expression25); - if (expression26 != null) expressions.add(expression26); - if (expression27 != null) expressions.add(expression27); - if (expression28 != null) expressions.add(expression28); - if (expression29 != null) expressions.add(expression29); - if (expression30 != null) expressions.add(expression30); + /// Gets a value from this map expression by key expression + Expression mapGet(Expression key) { + return _MapGetExpression(this, key); + } - return PipelineFilter._internal( - andExpression: null, - orExpression: _combineExpressions(expressions, 'or'), - ); + /// Gets a value from this map expression by literal key + Expression mapGetLiteral(String key) { + return _MapGetExpression(this, Constant(key)); } - /// Creates an AND filter combining multiple boolean expressions - static PipelineFilter and( - BooleanExpression expression1, [ - BooleanExpression? expression2, - BooleanExpression? expression3, - BooleanExpression? expression4, - BooleanExpression? expression5, - BooleanExpression? expression6, - BooleanExpression? expression7, - BooleanExpression? expression8, - BooleanExpression? expression9, - BooleanExpression? expression10, - BooleanExpression? expression11, - BooleanExpression? expression12, - BooleanExpression? expression13, - BooleanExpression? expression14, - BooleanExpression? expression15, - BooleanExpression? expression16, - BooleanExpression? expression17, - BooleanExpression? expression18, - BooleanExpression? expression19, - BooleanExpression? expression20, - BooleanExpression? expression21, - BooleanExpression? expression22, - BooleanExpression? expression23, - BooleanExpression? expression24, - BooleanExpression? expression25, - BooleanExpression? expression26, - BooleanExpression? expression27, - BooleanExpression? expression28, - BooleanExpression? expression29, - BooleanExpression? expression30, - ]) { - final expressions = [expression1]; - if (expression2 != null) expressions.add(expression2); + /// Returns the keys from this map expression + // ignore: use_to_and_as_if_applicable + Expression mapKeys() { + return _MapKeysExpression(this); + } + + /// Returns the values from this map expression + // ignore: use_to_and_as_if_applicable + Expression mapValues() { + return _MapValuesExpression(this); + } + + // ============================================================================ + // ALIASING + // ============================================================================ + + /// Assigns an alias to this expression for use in output + Selectable alias(String alias) { + return AliasedExpression(alias: alias, expression: this); + } + + // ============================================================================ + // ARITHMETIC OPERATIONS + // ============================================================================ + + /// Adds this expression to another expression + Expression add(Expression other) { + return _AddExpression(this, other); + } + + /// Adds a number to this expression + Expression addNumber(num other) { + return _AddExpression(this, Constant(other)); + } + + /// Subtracts another expression from this expression + Expression subtract(Expression other) { + return _SubtractExpression(this, other); + } + + /// Subtracts a number from this expression + Expression subtractNumber(num other) { + return _SubtractExpression(this, Constant(other)); + } + + /// Multiplies this expression by another expression + Expression multiply(Expression other) { + return _MultiplyExpression(this, other); + } + + /// Multiplies this expression by a number + Expression multiplyNumber(num other) { + return _MultiplyExpression(this, Constant(other)); + } + + /// Divides this expression by another expression + Expression divide(Expression other) { + return _DivideExpression(this, other); + } + + /// Divides this expression by a number + Expression divideNumber(num other) { + return _DivideExpression(this, Constant(other)); + } + + /// Returns the remainder of dividing this expression by another + Expression modulo(Expression other) { + return _ModuloExpression(this, other); + } + + /// Returns the remainder of dividing this expression by a number + Expression moduloNumber(num other) { + return _ModuloExpression(this, Constant(other)); + } + + /// Returns the absolute value of this expression + // ignore: use_to_and_as_if_applicable + Expression abs() { + return _AbsExpression(this); + } + + /// Returns the negation of this expression + // ignore: use_to_and_as_if_applicable + Expression negate() { + return _NegateExpression(this); + } + + // ============================================================================ + // COMPARISON OPERATIONS (return BooleanExpression) + // ============================================================================ + + /// Checks if this expression equals another expression + BooleanExpression equal(Expression other) { + return _EqualExpression(this, other); + } + + /// Checks if this expression equals a value + BooleanExpression equalValue(Object? value) { + return _EqualExpression(this, _toExpression(value)); + } + + /// Checks if this expression does not equal another expression + BooleanExpression notEqual(Expression other) { + return _NotEqualExpression(this, other); + } + + /// Checks if this expression does not equal a value + BooleanExpression notEqualValue(Object? value) { + return _NotEqualExpression(this, _toExpression(value)); + } + + /// Checks if this expression is greater than another expression + BooleanExpression greaterThan(Expression other) { + return _GreaterThanExpression(this, other); + } + + /// Checks if this expression is greater than a value + BooleanExpression greaterThanValue(Object? value) { + return _GreaterThanExpression(this, _toExpression(value)); + } + + /// Checks if this expression is greater than or equal to another expression + BooleanExpression greaterThanOrEqual(Expression other) { + return _GreaterThanOrEqualExpression(this, other); + } + + /// Checks if this expression is greater than or equal to a value + BooleanExpression greaterThanOrEqualValue(Object? value) { + return _GreaterThanOrEqualExpression(this, _toExpression(value)); + } + + /// Checks if this expression is less than another expression + BooleanExpression lessThan(Expression other) { + return _LessThanExpression(this, other); + } + + /// Checks if this expression is less than a value + BooleanExpression lessThanValue(Object? value) { + return _LessThanExpression(this, _toExpression(value)); + } + + /// Checks if this expression is less than or equal to another expression + BooleanExpression lessThanOrEqual(Expression other) { + return _LessThanOrEqualExpression(this, other); + } + + /// Checks if this expression is less than or equal to a value + BooleanExpression lessThanOrEqualValue(Object? value) { + return _LessThanOrEqualExpression(this, _toExpression(value)); + } + + // ============================================================================ + // STRING OPERATIONS + // ============================================================================ + + /// Returns the length of this string expression + // ignore: use_to_and_as_if_applicable + Expression length() { + return _LengthExpression(this); + } + + /// Concatenates this expression with other expressions/values + Expression concat(List others) { + final expressions = [this]; + for (final other in others) { + expressions.add(_toExpression(other)); + } + return _ConcatExpression(expressions); + } + + /// Converts this string expression to lowercase + Expression toLowerCase() { + return _ToLowerCaseExpression(this); + } + + /// Converts this string expression to uppercase + Expression toUpperCase() { + return _ToUpperCaseExpression(this); + } + + /// Extracts a substring from this string expression + Expression substring(Expression start, Expression end) { + return _SubstringExpression(this, start, end); + } + + /// Extracts a substring using literal indices + Expression substringLiteral(int start, int end) { + return _SubstringExpression(this, Constant(start), Constant(end)); + } + + /// Replaces occurrences of a pattern in this string + Expression replace(Expression find, Expression replacement) { + return _ReplaceExpression(this, find, replacement); + } + + /// Replaces occurrences of a string literal + Expression replaceLiteral(String find, String replacement) { + return _ReplaceExpression(this, Constant(find), Constant(replacement)); + } + + /// Splits this string expression by a delimiter + Expression split(Expression delimiter) { + return _SplitExpression(this, delimiter); + } + + /// Splits this string by a literal delimiter + Expression splitLiteral(String delimiter) { + return _SplitExpression(this, Constant(delimiter)); + } + + /// Joins array elements with a delimiter + Expression join(Expression delimiter) { + return _JoinExpression(this, delimiter); + } + + /// Joins array elements with a literal delimiter + Expression joinLiteral(String delimiter) { + return _JoinExpression(this, Constant(delimiter)); + } + + /// Trims whitespace from this string expression + // ignore: use_to_and_as_if_applicable + Expression trim() { + return _TrimExpression(this); + } + + // ============================================================================ + // ARRAY OPERATIONS + // ============================================================================ + + /// Concatenates this array with another array expression + Expression arrayConcat(Expression secondArray) { + return _ArrayConcatExpression(this, secondArray); + } + + /// Concatenates this array with multiple arrays/values + Expression arrayConcatMultiple(List otherArrays) { + final expressions = [this]; + for (final other in otherArrays) { + expressions.add(_toExpression(other)); + } + return _ArrayConcatMultipleExpression(expressions); + } + + /// Checks if this array contains an element expression + BooleanExpression arrayContainsElement(Expression element) { + return _ArrayContainsExpression(this, element); + } + + /// Checks if this array contains a value + BooleanExpression arrayContainsValue(Object? element) { + return _ArrayContainsExpression(this, _toExpression(element)); + } + + /// Returns the length of this array expression + // ignore: use_to_and_as_if_applicable + Expression arrayLength() { + return _ArrayLengthExpression(this); + } + + /// Reverses this array expression + // ignore: use_to_and_as_if_applicable + Expression arrayReverse() { + return _ArrayReverseExpression(this); + } + + /// Returns the sum of numeric elements in this array + // ignore: use_to_and_as_if_applicable + Expression arraySum() { + return _ArraySumExpression(this); + } + + /// Extracts a slice from this array + Expression arraySlice(Expression start, Expression end) { + return _ArraySliceExpression(this, start, end); + } + + /// Extracts a slice using literal indices + Expression arraySliceLiteral(int start, int end) { + return _ArraySliceExpression(this, Constant(start), Constant(end)); + } + + // ============================================================================ + // AGGREGATE FUNCTIONS + // ============================================================================ + + /// Creates a sum aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction sum() { + return Sum(this); + } + + /// Creates an average aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction average() { + return Average(this); + } + + /// Creates a count aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction count() { + return Count(this); + } + + /// Creates a count distinct aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction countDistinct() { + return CountDistinct(this); + } + + /// Creates a minimum aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction minimum() { + return Minimum(this); + } + + /// Creates a maximum aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction maximum() { + return Maximum(this); + } + + String get name; + + @override + Map toMap() { + return { + 'name': name, + }; + } + + // ============================================================================ + // STATIC FACTORY METHODS + // ============================================================================ + + /// Creates a constant expression from a string value + static Expression constantString(String value) => Constant(value); + + /// Creates a constant expression from a number value + static Expression constantNumber(num value) => Constant(value); + + /// Creates a constant expression from a boolean value + static Expression constantBoolean(bool value) => Constant(value); + + /// Creates a constant expression from a DateTime value + static Expression constantDateTime(DateTime value) => Constant(value); + + /// Creates a constant expression from a Timestamp value + static Expression constantTimestamp(Timestamp value) => Constant(value); + + /// Creates a constant expression from a GeoPoint value + static Expression constantGeoPoint(GeoPoint value) => Constant(value); + + /// Creates a constant expression from a Blob value + static Expression constantBlob(Blob value) => Constant(value); + + /// Creates a constant expression from a DocumentReference value + static Expression constantDocumentReference(DocumentReference value) => + Constant(value); + + /// Creates a constant expression from a byte array value + static Expression constantBytes(List value) => Constant(value); + + /// Creates a constant expression from a VectorValue value + static Expression constantVector(VectorValue value) => Constant(value); + + /// Creates a constant expression from any value (convenience) + static Expression constant(Object? value) => Constant(value!); + + /// Creates a field reference expression from a field path string + static Field field(String fieldPath) => Field(fieldPath); + + /// Creates a field reference expression from a FieldPath object + static Field fieldPath(FieldPath fieldPath) => Field(fieldPath.toString()); + + /// Creates a null value expression + static Expression nullValue() => _NullExpression(); + + /// Creates a conditional (ternary) expression + static Expression conditional( + BooleanExpression condition, + Expression thenExpr, + Expression elseExpr, + ) { + return _ConditionalExpression(condition, thenExpr, elseExpr); + } + + /// Creates a conditional expression with literal values + static Expression conditionalValues( + BooleanExpression condition, + Object? thenValue, + Object? elseValue, + ) { + return _ConditionalExpression( + condition, + _toExpression(thenValue), + _toExpression(elseValue), + ); + } + + /// Creates an array expression from elements + static Expression array(List elements) { + return _ArrayExpression( + elements.map(_toExpression).toList(), + ); + } + + /// Creates a map expression from key-value pairs + static Expression map(Map data) { + return _MapExpression(data.map((k, v) => MapEntry(k, _toExpression(v)))); + } + + /// Creates a map expression from alternating key-value expressions + static Expression mapFromPairs(List keyValuePairs) { + return _MapFromPairsExpression(keyValuePairs); + } + + /// Returns the current timestamp + static Expression currentTimestamp() { + return _CurrentTimestampExpression(); + } + + /// Adds time to a timestamp expression + static Expression timestampAdd( + Expression timestamp, + String unit, + Expression amount, + ) { + return _TimestampAddExpression(timestamp, unit, amount); + } + + /// Adds time to a timestamp with a literal amount + static Expression timestampAddLiteral( + Expression timestamp, + String unit, + int amount, + ) { + return _TimestampAddExpression(timestamp, unit, Constant(amount)); + } + + /// Subtracts time from a timestamp expression + static Expression timestampSubtract( + Expression timestamp, + String unit, + Expression amount, + ) { + return _TimestampSubtractExpression(timestamp, unit, amount); + } + + /// Subtracts time from a timestamp with a literal amount + static Expression timestampSubtractLiteral( + Expression timestamp, + String unit, + int amount, + ) { + return _TimestampSubtractExpression(timestamp, unit, Constant(amount)); + } + + /// Calculates the difference between two timestamps + static Expression timestampDiff( + Expression timestamp1, + Expression timestamp2, + String unit, + ) { + return _TimestampDiffExpression(timestamp1, timestamp2, unit); + } + + /// Truncates a timestamp to a specific unit + static Expression timestampTruncate( + Expression timestamp, + String unit, + ) { + return _TimestampTruncateExpression(timestamp, unit); + } + + /// Calculates the distance between two GeoPoint expressions + static Expression distance( + Expression geoPoint1, + Expression geoPoint2, + ) { + return _DistanceExpression(geoPoint1, geoPoint2); + } + + /// Creates a document ID expression from a DocumentReference + static Expression documentIdFromRef(DocumentReference docRef) { + return _DocumentIdFromRefExpression(docRef); + } + + /// Checks if a value is in a list (IN operator) + static BooleanExpression equalAny( + Expression value, + List values, + ) { + return _EqualAnyExpression(value, values.map(_toExpression).toList()); + } + + /// Checks if a value is not in a list (NOT IN operator) + static BooleanExpression notEqualAny( + Expression value, + List values, + ) { + return _NotEqualAnyExpression(value, values.map(_toExpression).toList()); + } + + /// Checks if a field exists in the document + static BooleanExpression existsField(String fieldName) { + return _ExistsExpression(Field(fieldName)); + } + + /// Returns an expression if another is absent + static Expression ifAbsentStatic( + Expression ifExpr, + Expression elseExpr, + ) { + return _IfAbsentExpression(ifExpr, elseExpr); + } + + /// Returns a value if an expression is absent + static Expression ifAbsentValueStatic( + Expression ifExpr, + Object? elseValue, + ) { + return _IfAbsentExpression(ifExpr, _toExpression(elseValue)); + } + + /// Checks if an expression is absent + static BooleanExpression isAbsentStatic(Expression value) { + return _IsAbsentExpression(value); + } + + /// Checks if a field is absent + static BooleanExpression isAbsentField(String fieldName) { + return _IsAbsentExpression(Field(fieldName)); + } + + /// Returns an expression if another errors + static BooleanExpression ifErrorStatic( + BooleanExpression tryExpr, + BooleanExpression catchExpr, + ) { + return _IfErrorExpression(tryExpr, catchExpr) as BooleanExpression; + } + + /// Checks if an expression produces an error + static BooleanExpression isErrorStatic(Expression expr) { + return _IsErrorExpression(expr); + } + + /// Joins array elements with a delimiter + static Expression joinStatic( + Expression arrayExpression, + Expression delimiterExpression, + ) { + return _JoinExpression(arrayExpression, delimiterExpression); + } + + /// Joins array elements with a literal delimiter + static Expression joinStaticLiteral( + Expression arrayExpression, + String delimiter, + ) { + return _JoinExpression(arrayExpression, Constant(delimiter)); + } + + /// Joins a field's array with a delimiter + static Expression joinField( + String arrayFieldName, + String delimiter, + ) { + return _JoinExpression(Field(arrayFieldName), Constant(delimiter)); + } + + /// Concatenates arrays + static Expression arrayConcatStatic( + Expression firstArray, + Expression secondArray, + List? otherArrays, + ) { + final expressions = [firstArray, secondArray]; + if (otherArrays != null) { + for (final other in otherArrays) { + expressions.add(_toExpression(other)); + } + } + return _ArrayConcatMultipleExpression(expressions); + } + + /// Returns the length of an expression + static Expression lengthStatic(Expression expr) { + return _LengthExpression(expr); + } + + /// Returns the length of a field + static Expression lengthField(String fieldName) { + return _LengthExpression(Field(fieldName)); + } + + /// Returns the absolute value of an expression + static Expression absStatic(Expression numericExpr) { + return _AbsExpression(numericExpr); + } + + /// Returns the absolute value of a field + static Expression absField(String numericField) { + return _AbsExpression(Field(numericField)); + } + + /// Negates an expression + static Expression negateStatic(Expression numericExpr) { + return _NegateExpression(numericExpr); + } + + /// Negates a field + static Expression negateField(String numericField) { + return _NegateExpression(Field(numericField)); + } + + /// Adds two expressions + static Expression addStatic( + Expression first, + Expression second, + ) { + return _AddExpression(first, second); + } + + /// Adds an expression and a number + static Expression addStaticNumber( + Expression first, + num second, + ) { + return _AddExpression(first, Constant(second)); + } + + /// Adds a field and an expression + static Expression addField( + String numericFieldName, + Expression second, + ) { + return _AddExpression(Field(numericFieldName), second); + } + + /// Adds a field and a number + static Expression addFieldNumber( + String numericFieldName, + num second, + ) { + return _AddExpression(Field(numericFieldName), Constant(second)); + } + + /// Subtracts two expressions + static Expression subtractStatic( + Expression minuend, + Expression subtrahend, + ) { + return _SubtractExpression(minuend, subtrahend); + } + + /// Multiplies two expressions + static Expression multiplyStatic( + Expression multiplicand, + Expression multiplier, + ) { + return _MultiplyExpression(multiplicand, multiplier); + } + + /// Divides two expressions + static Expression divideStatic( + Expression dividend, + Expression divisor, + ) { + return _DivideExpression(dividend, divisor); + } + + /// Returns modulo of two expressions + static Expression moduloStatic( + Expression dividend, + Expression divisor, + ) { + return _ModuloExpression(dividend, divisor); + } + + /// Compares two expressions for equality + static BooleanExpression equalStatic( + Expression left, + Expression right, + ) { + return _EqualExpression(left, right); + } + + /// Compares expression with value for equality + static BooleanExpression equalStaticValue( + Expression left, + Object? right, + ) { + return _EqualExpression(left, _toExpression(right)); + } + + /// Compares field with value for equality + static BooleanExpression equalField( + String fieldName, + Object? value, + ) { + return _EqualExpression(Field(fieldName), _toExpression(value)); + } + + /// Compares two expressions for inequality + static BooleanExpression notEqualStatic( + Expression left, + Expression right, + ) { + return _NotEqualExpression(left, right); + } + + /// Compares expression with value for inequality + static BooleanExpression notEqualStaticValue( + Expression left, + Object? right, + ) { + return _NotEqualExpression(left, _toExpression(right)); + } + + /// Greater than comparison + static BooleanExpression greaterThanStatic( + Expression left, + Expression right, + ) { + return _GreaterThanExpression(left, right); + } + + /// Greater than comparison with value + static BooleanExpression greaterThanStaticValue( + Expression left, + Object? right, + ) { + return _GreaterThanExpression(left, _toExpression(right)); + } + + /// Greater than comparison for field + static BooleanExpression greaterThanField( + String fieldName, + Object? value, + ) { + return _GreaterThanExpression(Field(fieldName), _toExpression(value)); + } + + /// Greater than or equal comparison + static BooleanExpression greaterThanOrEqualStatic( + Expression left, + Expression right, + ) { + return _GreaterThanOrEqualExpression(left, right); + } + + /// Less than comparison + static BooleanExpression lessThanStatic( + Expression left, + Expression right, + ) { + return _LessThanExpression(left, right); + } + + /// Less than comparison with value + static BooleanExpression lessThanStaticValue( + Expression left, + Object? right, + ) { + return _LessThanExpression(left, _toExpression(right)); + } + + /// Less than comparison for field + static BooleanExpression lessThanField( + String fieldName, + Object? value, + ) { + return _LessThanExpression(Field(fieldName), _toExpression(value)); + } + + /// Less than or equal comparison + static BooleanExpression lessThanOrEqualStatic( + Expression left, + Expression right, + ) { + return _LessThanOrEqualExpression(left, right); + } + + /// Concatenates expressions + static Expression concatStatic( + Expression first, + Expression second, + List? others, + ) { + final expressions = [first, second]; + if (others != null) { + for (final other in others) { + expressions.add(_toExpression(other)); + } + } + return _ConcatExpression(expressions); + } + + /// Converts to lowercase + static Expression toLowerCaseStatic(Expression stringExpr) { + return _ToLowerCaseExpression(stringExpr); + } + + /// Converts field to lowercase + static Expression toLowerCaseField(String stringField) { + return _ToLowerCaseExpression(Field(stringField)); + } + + /// Converts to uppercase + static Expression toUpperCaseStatic(Expression stringExpr) { + return _ToUpperCaseExpression(stringExpr); + } + + /// Converts field to uppercase + static Expression toUpperCaseField(String stringField) { + return _ToUpperCaseExpression(Field(stringField)); + } + + /// Trims whitespace + static Expression trimStatic(Expression stringExpr) { + return _TrimExpression(stringExpr); + } + + /// Trims field whitespace + static Expression trimField(String stringField) { + return _TrimExpression(Field(stringField)); + } + + /// Extracts substring + static Expression substringStatic( + Expression stringExpr, + Expression start, + Expression end, + ) { + return _SubstringExpression(stringExpr, start, end); + } + + /// Replaces in string + static Expression replaceStatic( + Expression stringExpr, + Expression find, + Expression replacement, + ) { + return _ReplaceExpression(stringExpr, find, replacement); + } + + /// Splits string + static Expression splitStatic( + Expression stringExpr, + Expression delimiter, + ) { + return _SplitExpression(stringExpr, delimiter); + } + + /// Reverses array + static Expression arrayReverseStatic(Expression array) { + return _ArrayReverseExpression(array); + } + + /// Reverses field array + static Expression arrayReverseField(String arrayFieldName) { + return _ArrayReverseExpression(Field(arrayFieldName)); + } + + /// Sums array + static Expression arraySumStatic(Expression array) { + return _ArraySumExpression(array); + } + + /// Sums field array + static Expression arraySumField(String arrayFieldName) { + return _ArraySumExpression(Field(arrayFieldName)); + } + + /// Gets array length + static Expression arrayLengthStatic(Expression array) { + return _ArrayLengthExpression(array); + } + + /// Gets field array length + static Expression arrayLengthField(String arrayFieldName) { + return _ArrayLengthExpression(Field(arrayFieldName)); + } + + /// Slices array + static Expression arraySliceStatic( + Expression array, + Expression start, + Expression end, + ) { + return _ArraySliceExpression(array, start, end); + } + + /// Checks array contains + static BooleanExpression arrayContainsElementStatic( + Expression array, + Expression element, + ) { + return _ArrayContainsExpression(array, element); + } + + /// Checks field array contains + static BooleanExpression arrayContainsField( + String arrayFieldName, + Object? element, + ) { + return _ArrayContainsExpression( + Field(arrayFieldName), _toExpression(element)); + } + + /// Creates a raw/custom function expression + static Expression rawFunction( + String name, + List args, + ) { + return _RawFunctionExpression(name, args); + } +} + +/// Base class for function expressions +abstract class FunctionExpression extends Expression {} + +/// Base class for selectable expressions (can be used in select stage) +abstract class Selectable extends Expression { + String get aliasName; + Expression get expression; +} + +/// Represents an aliased expression wrapper +class AliasedExpression extends Selectable { + final String _alias; + + @override + String get aliasName => _alias; + + @override + final Expression expression; + + AliasedExpression({ + required String alias, + required this.expression, + }) : _alias = alias; + + @override + String get name => 'alias'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'alias': _alias, + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a field reference in a pipeline expression +class Field extends Selectable { + final String fieldName; + + Field(this.fieldName); + + @override + String get name => 'field'; + + @override + String get aliasName => fieldName; + + @override + Expression get expression => this; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'field': fieldName, + }, + }; + } +} + +/// Represents a null value expression +class _NullExpression extends Expression { + _NullExpression(); + + @override + String get name => 'null'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'value': null, + }, + }; + } +} + +/// Represents a constant value in a pipeline expression +class Constant extends Expression { + final Object value; + + Constant(this.value); + + @override + String get name => 'constant'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'value': value, + }, + }; + } +} + +/// Represents a concatenation function expression +class Concat extends FunctionExpression { + final List expressions; + + Concat(this.expressions); + + @override + String get name => 'concat'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a concat function expression (internal) +class _ConcatExpression extends FunctionExpression { + final List expressions; + + _ConcatExpression(this.expressions); + + @override + String get name => 'concat'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a length function expression +class _LengthExpression extends FunctionExpression { + final Expression expression; + + _LengthExpression(this.expression); + + @override + String get name => 'length'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a toLowerCase function expression +class _ToLowerCaseExpression extends FunctionExpression { + final Expression expression; + + _ToLowerCaseExpression(this.expression); + + @override + String get name => 'to_lower_case'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a toUpperCase function expression +class _ToUpperCaseExpression extends FunctionExpression { + final Expression expression; + + _ToUpperCaseExpression(this.expression); + + @override + String get name => 'to_upper_case'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a substring function expression +class _SubstringExpression extends FunctionExpression { + final Expression expression; + final Expression start; + final Expression end; + + _SubstringExpression(this.expression, this.start, this.end); + + @override + String get name => 'substring'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'start': start.toMap(), + 'end': end.toMap(), + }, + }; + } +} + +/// Represents a replace function expression +class _ReplaceExpression extends FunctionExpression { + final Expression expression; + final Expression find; + final Expression replacement; + + _ReplaceExpression(this.expression, this.find, this.replacement); + + @override + String get name => 'replace'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'find': find.toMap(), + 'replacement': replacement.toMap(), + }, + }; + } +} + +/// Represents a split function expression +class _SplitExpression extends FunctionExpression { + final Expression expression; + final Expression delimiter; + + _SplitExpression(this.expression, this.delimiter); + + @override + String get name => 'split'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'delimiter': delimiter.toMap(), + }, + }; + } +} + +/// Represents a join function expression +class _JoinExpression extends FunctionExpression { + final Expression expression; + final Expression delimiter; + + _JoinExpression(this.expression, this.delimiter); + + @override + String get name => 'join'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'delimiter': delimiter.toMap(), + }, + }; + } +} + +/// Represents a trim function expression +class _TrimExpression extends FunctionExpression { + final Expression expression; + + _TrimExpression(this.expression); + + @override + String get name => 'trim'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Base class for boolean expressions used in filtering +abstract class BooleanExpression extends Expression {} + +/// Represents a filter expression for pipeline where clauses +class PipelineFilter extends BooleanExpression { + final Object field; + final Object? isEqualTo; + final Object? isNotEqualTo; + final Object? isLessThan; + final Object? isLessThanOrEqualTo; + final Object? isGreaterThan; + final Object? isGreaterThanOrEqualTo; + final Object? arrayContains; + final List? arrayContainsAny; + final List? whereIn; + final List? whereNotIn; + final bool? isNull; + final bool? isNotNull; + final BooleanExpression? _andExpression; + final BooleanExpression? _orExpression; + + PipelineFilter( + this.field, { + this.isEqualTo, + this.isNotEqualTo, + this.isLessThan, + this.isLessThanOrEqualTo, + this.isGreaterThan, + this.isGreaterThanOrEqualTo, + this.arrayContains, + this.arrayContainsAny, + this.whereIn, + this.whereNotIn, + this.isNull, + this.isNotNull, + }) : _andExpression = null, + _orExpression = null; + + PipelineFilter._internal({ + required BooleanExpression? andExpression, + required BooleanExpression? orExpression, + }) : field = '', + isEqualTo = null, + isNotEqualTo = null, + isLessThan = null, + isLessThanOrEqualTo = null, + isGreaterThan = null, + isGreaterThanOrEqualTo = null, + arrayContains = null, + arrayContainsAny = null, + whereIn = null, + whereNotIn = null, + isNull = null, + isNotNull = null, + _andExpression = andExpression, + _orExpression = orExpression; + + /// Creates an OR filter combining multiple boolean expressions + static PipelineFilter or( + BooleanExpression expression1, [ + BooleanExpression? expression2, + BooleanExpression? expression3, + BooleanExpression? expression4, + BooleanExpression? expression5, + BooleanExpression? expression6, + BooleanExpression? expression7, + BooleanExpression? expression8, + BooleanExpression? expression9, + BooleanExpression? expression10, + BooleanExpression? expression11, + BooleanExpression? expression12, + BooleanExpression? expression13, + BooleanExpression? expression14, + BooleanExpression? expression15, + BooleanExpression? expression16, + BooleanExpression? expression17, + BooleanExpression? expression18, + BooleanExpression? expression19, + BooleanExpression? expression20, + BooleanExpression? expression21, + BooleanExpression? expression22, + BooleanExpression? expression23, + BooleanExpression? expression24, + BooleanExpression? expression25, + BooleanExpression? expression26, + BooleanExpression? expression27, + BooleanExpression? expression28, + BooleanExpression? expression29, + BooleanExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); if (expression3 != null) expressions.add(expression3); if (expression4 != null) expressions.add(expression4); if (expression5 != null) expressions.add(expression5); @@ -332,80 +1543,1391 @@ class PipelineFilter extends BooleanExpression { if (expression29 != null) expressions.add(expression29); if (expression30 != null) expressions.add(expression30); - return PipelineFilter._internal( - andExpression: _combineExpressions(expressions, 'and'), - orExpression: null, - ); + return PipelineFilter._internal( + andExpression: null, + orExpression: _combineExpressions(expressions, 'or'), + ); + } + + /// Creates an AND filter combining multiple boolean expressions + static PipelineFilter and( + BooleanExpression expression1, [ + BooleanExpression? expression2, + BooleanExpression? expression3, + BooleanExpression? expression4, + BooleanExpression? expression5, + BooleanExpression? expression6, + BooleanExpression? expression7, + BooleanExpression? expression8, + BooleanExpression? expression9, + BooleanExpression? expression10, + BooleanExpression? expression11, + BooleanExpression? expression12, + BooleanExpression? expression13, + BooleanExpression? expression14, + BooleanExpression? expression15, + BooleanExpression? expression16, + BooleanExpression? expression17, + BooleanExpression? expression18, + BooleanExpression? expression19, + BooleanExpression? expression20, + BooleanExpression? expression21, + BooleanExpression? expression22, + BooleanExpression? expression23, + BooleanExpression? expression24, + BooleanExpression? expression25, + BooleanExpression? expression26, + BooleanExpression? expression27, + BooleanExpression? expression28, + BooleanExpression? expression29, + BooleanExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + + return PipelineFilter._internal( + andExpression: _combineExpressions(expressions, 'and'), + orExpression: null, + ); + } + + static BooleanExpression _combineExpressions( + List expressions, + String operator, + ) { + if (expressions.length == 1) return expressions.first; + + // Create a nested structure for multiple expressions + BooleanExpression result = expressions.first; + for (int i = 1; i < expressions.length; i++) { + if (operator == 'and') { + result = PipelineFilter.and(result, expressions[i]); + } else { + result = PipelineFilter.or(result, expressions[i]); + } + } + return result; + } + + @override + String get name => 'filter'; + + @override + Map toMap() { + final map = super.toMap(); + + if (_andExpression != null) { + map['args'] = { + 'operator': 'and', + 'expressions': [_andExpression.toMap()], + }; + return map; + } + + if (_orExpression != null) { + map['args'] = { + 'operator': 'or', + 'expressions': [_orExpression.toMap()], + }; + return map; + } + + final args = {}; + if (field is String) { + args['field'] = field; + } else if (field is Field) { + args['field'] = (field as Field).fieldName; + } + + if (isEqualTo != null) args['isEqualTo'] = isEqualTo; + if (isNotEqualTo != null) args['isNotEqualTo'] = isNotEqualTo; + if (isLessThan != null) args['isLessThan'] = isLessThan; + if (isLessThanOrEqualTo != null) { + args['isLessThanOrEqualTo'] = isLessThanOrEqualTo; + } + if (isGreaterThan != null) args['isGreaterThan'] = isGreaterThan; + if (isGreaterThanOrEqualTo != null) { + args['isGreaterThanOrEqualTo'] = isGreaterThanOrEqualTo; + } + if (arrayContains != null) args['arrayContains'] = arrayContains; + if (arrayContainsAny != null) { + args['arrayContainsAny'] = arrayContainsAny; + } + if (whereIn != null) args['whereIn'] = whereIn; + if (whereNotIn != null) args['whereNotIn'] = whereNotIn; + if (isNull != null) args['isNull'] = isNull; + if (isNotNull != null) args['isNotNull'] = isNotNull; + + map['args'] = args; + return map; + } +} + +// ============================================================================ +// PATTERN DEMONSTRATION - Concrete Function Expression Classes +// ============================================================================ + +/// Represents an addition function expression +class _AddExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _AddExpression(this.left, this.right); + + @override + String get name => 'add'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a subtraction function expression +class _SubtractExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _SubtractExpression(this.left, this.right); + + @override + String get name => 'subtract'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents an equality comparison function expression +class _EqualExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _EqualExpression(this.left, this.right); + + @override + String get name => 'equal'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a greater-than comparison function expression +class _GreaterThanExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _GreaterThanExpression(this.left, this.right); + + @override + String get name => 'greater_than'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a multiply function expression +class _MultiplyExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _MultiplyExpression(this.left, this.right); + + @override + String get name => 'multiply'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a divide function expression +class _DivideExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _DivideExpression(this.left, this.right); + + @override + String get name => 'divide'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a modulo function expression +class _ModuloExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _ModuloExpression(this.left, this.right); + + @override + String get name => 'modulo'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents an absolute value function expression +class _AbsExpression extends FunctionExpression { + final Expression expression; + + _AbsExpression(this.expression); + + @override + String get name => 'abs'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a negation function expression +class _NegateExpression extends FunctionExpression { + final Expression expression; + + _NegateExpression(this.expression); + + @override + String get name => 'negate'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a not-equal comparison function expression +class _NotEqualExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _NotEqualExpression(this.left, this.right); + + @override + String get name => 'not_equal'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a greater-than-or-equal comparison function expression +class _GreaterThanOrEqualExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _GreaterThanOrEqualExpression(this.left, this.right); + + @override + String get name => 'greater_than_or_equal'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a less-than comparison function expression +class _LessThanExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _LessThanExpression(this.left, this.right); + + @override + String get name => 'less_than'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a less-than-or-equal comparison function expression +class _LessThanOrEqualExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _LessThanOrEqualExpression(this.left, this.right); + + @override + String get name => 'less_than_or_equal'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +// ============================================================================ +// ARRAY OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents an array concat function expression +class _ArrayConcatExpression extends FunctionExpression { + final Expression firstArray; + final Expression secondArray; + + _ArrayConcatExpression(this.firstArray, this.secondArray); + + @override + String get name => 'array_concat'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'first': firstArray.toMap(), + 'second': secondArray.toMap(), + }, + }; + } +} + +/// Represents an array concat multiple function expression +class _ArrayConcatMultipleExpression extends FunctionExpression { + final List arrays; + + _ArrayConcatMultipleExpression(this.arrays); + + @override + String get name => 'array_concat_multiple'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'arrays': arrays.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents an array contains function expression +class _ArrayContainsExpression extends BooleanExpression { + final Expression array; + final Expression element; + + _ArrayContainsExpression(this.array, this.element); + + @override + String get name => 'array_contains'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'array': array.toMap(), + 'element': element.toMap(), + }, + }; + } +} + +/// Represents an array length function expression +class _ArrayLengthExpression extends FunctionExpression { + final Expression expression; + + _ArrayLengthExpression(this.expression); + + @override + String get name => 'array_length'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an array reverse function expression +class _ArrayReverseExpression extends FunctionExpression { + final Expression expression; + + _ArrayReverseExpression(this.expression); + + @override + String get name => 'array_reverse'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an array sum function expression +class _ArraySumExpression extends FunctionExpression { + final Expression expression; + + _ArraySumExpression(this.expression); + + @override + String get name => 'array_sum'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an array slice function expression +class _ArraySliceExpression extends FunctionExpression { + final Expression array; + final Expression start; + final Expression end; + + _ArraySliceExpression(this.array, this.start, this.end); + + @override + String get name => 'array_slice'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'array': array.toMap(), + 'start': start.toMap(), + 'end': end.toMap(), + }, + }; + } +} + +// ============================================================================ +// CONDITIONAL / LOGIC OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents an ifAbsent function expression +class _IfAbsentExpression extends FunctionExpression { + final Expression expression; + final Expression elseExpr; + + _IfAbsentExpression(this.expression, this.elseExpr); + + @override + String get name => 'if_absent'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'else': elseExpr.toMap(), + }, + }; + } +} + +/// Represents an ifError function expression +class _IfErrorExpression extends FunctionExpression { + final Expression expression; + final Expression catchExpr; + + _IfErrorExpression(this.expression, this.catchExpr); + + @override + String get name => 'if_error'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'catch': catchExpr.toMap(), + }, + }; + } +} + +/// Represents an isAbsent function expression +class _IsAbsentExpression extends BooleanExpression { + final Expression expression; + + _IsAbsentExpression(this.expression); + + @override + String get name => 'is_absent'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an isError function expression +class _IsErrorExpression extends BooleanExpression { + final Expression expression; + + _IsErrorExpression(this.expression); + + @override + String get name => 'is_error'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an exists function expression +class _ExistsExpression extends BooleanExpression { + final Expression expression; + + _ExistsExpression(this.expression); + + @override + String get name => 'exists'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a conditional (ternary) function expression +class _ConditionalExpression extends FunctionExpression { + final BooleanExpression condition; + final Expression thenExpr; + final Expression elseExpr; + + _ConditionalExpression(this.condition, this.thenExpr, this.elseExpr); + + @override + String get name => 'conditional'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'condition': condition.toMap(), + 'then': thenExpr.toMap(), + 'else': elseExpr.toMap(), + }, + }; + } +} + +// ============================================================================ +// TYPE CONVERSION EXPRESSION CLASSES +// ============================================================================ + +/// Represents an asBoolean function expression +class _AsBooleanExpression extends BooleanExpression { + final Expression expression; + + _AsBooleanExpression(this.expression); + + @override + String get name => 'as_boolean'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a toStringWithFormat function expression +class _ToStringWithFormatExpression extends FunctionExpression { + final Expression expression; + final Expression format; + + _ToStringWithFormatExpression(this.expression, this.format); + + @override + String get name => 'to_string_with_format'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'format': format.toMap(), + }, + }; + } +} + +// ============================================================================ +// BITWISE OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents a bitAnd function expression +class _BitAndExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _BitAndExpression(this.left, this.right); + + @override + String get name => 'bit_and'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a bitOr function expression +class _BitOrExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _BitOrExpression(this.left, this.right); + + @override + String get name => 'bit_or'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a bitXor function expression +class _BitXorExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _BitXorExpression(this.left, this.right); + + @override + String get name => 'bit_xor'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a bitNot function expression +class _BitNotExpression extends FunctionExpression { + final Expression expression; + + _BitNotExpression(this.expression); + + @override + String get name => 'bit_not'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a bitLeftShift function expression +class _BitLeftShiftExpression extends FunctionExpression { + final Expression expression; + final Expression amount; + + _BitLeftShiftExpression(this.expression, this.amount); + + @override + String get name => 'bit_left_shift'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'amount': amount.toMap(), + }, + }; + } +} + +/// Represents a bitRightShift function expression +class _BitRightShiftExpression extends FunctionExpression { + final Expression expression; + final Expression amount; + + _BitRightShiftExpression(this.expression, this.amount); + + @override + String get name => 'bit_right_shift'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'amount': amount.toMap(), + }, + }; + } +} + +// ============================================================================ +// DOCUMENT / PATH OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents a documentId function expression +class _DocumentIdExpression extends FunctionExpression { + final Expression expression; + + _DocumentIdExpression(this.expression); + + @override + String get name => 'document_id'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a collectionId function expression +class _CollectionIdExpression extends FunctionExpression { + final Expression expression; + + _CollectionIdExpression(this.expression); + + @override + String get name => 'collection_id'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a documentIdFromRef function expression +class _DocumentIdFromRefExpression extends FunctionExpression { + final DocumentReference docRef; + + _DocumentIdFromRefExpression(this.docRef); + + @override + String get name => 'document_id_from_ref'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'doc_ref': docRef.path, + }, + }; + } +} + +// ============================================================================ +// MAP OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents a mapGet function expression +class _MapGetExpression extends FunctionExpression { + final Expression map; + final Expression key; + + _MapGetExpression(this.map, this.key); + + @override + String get name => 'map_get'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'map': map.toMap(), + 'key': key.toMap(), + }, + }; + } +} + +/// Represents a mapKeys function expression +class _MapKeysExpression extends FunctionExpression { + final Expression expression; + + _MapKeysExpression(this.expression); + + @override + String get name => 'map_keys'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a mapValues function expression +class _MapValuesExpression extends FunctionExpression { + final Expression expression; + + _MapValuesExpression(this.expression); + + @override + String get name => 'map_values'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +// ============================================================================ +// TIMESTAMP OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents a currentTimestamp function expression +class _CurrentTimestampExpression extends FunctionExpression { + _CurrentTimestampExpression(); + + @override + String get name => 'current_timestamp'; + + @override + Map toMap() { + return { + 'name': name, + }; + } +} + +/// Represents a timestampAdd function expression +class _TimestampAddExpression extends FunctionExpression { + final Expression timestamp; + final String unit; + final Expression amount; + + _TimestampAddExpression(this.timestamp, this.unit, this.amount); + + @override + String get name => 'timestamp_add'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'timestamp': timestamp.toMap(), + 'unit': unit, + 'amount': amount.toMap(), + }, + }; } +} - static BooleanExpression _combineExpressions( - List expressions, - String operator, - ) { - if (expressions.length == 1) return expressions.first; +/// Represents a timestampSubtract function expression +class _TimestampSubtractExpression extends FunctionExpression { + final Expression timestamp; + final String unit; + final Expression amount; - // Create a nested structure for multiple expressions - BooleanExpression result = expressions.first; - for (int i = 1; i < expressions.length; i++) { - if (operator == 'and') { - result = PipelineFilter.and(result, expressions[i]); - } else { - result = PipelineFilter.or(result, expressions[i]); - } - } - return result; + _TimestampSubtractExpression(this.timestamp, this.unit, this.amount); + + @override + String get name => 'timestamp_subtract'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'timestamp': timestamp.toMap(), + 'unit': unit, + 'amount': amount.toMap(), + }, + }; } +} + +/// Represents a timestampDiff function expression +class _TimestampDiffExpression extends FunctionExpression { + final Expression timestamp1; + final Expression timestamp2; + final String unit; + + _TimestampDiffExpression(this.timestamp1, this.timestamp2, this.unit); @override - String get name => 'filter'; + String get name => 'timestamp_diff'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'timestamp1': timestamp1.toMap(), + 'timestamp2': timestamp2.toMap(), + 'unit': unit, + }, + }; + } +} + +/// Represents a timestampTruncate function expression +class _TimestampTruncateExpression extends FunctionExpression { + final Expression timestamp; + final String unit; + + _TimestampTruncateExpression(this.timestamp, this.unit); + + @override + String get name => 'timestamp_truncate'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'timestamp': timestamp.toMap(), + 'unit': unit, + }, + }; + } +} + +/// Represents a distance function expression +class _DistanceExpression extends FunctionExpression { + final Expression geoPoint1; + final Expression geoPoint2; + + _DistanceExpression(this.geoPoint1, this.geoPoint2); + + @override + String get name => 'distance'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'geo_point1': geoPoint1.toMap(), + 'geo_point2': geoPoint2.toMap(), + }, + }; + } +} + +// ============================================================================ +// SPECIAL OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents an equalAny (IN) function expression +class _EqualAnyExpression extends BooleanExpression { + final Expression value; + final List values; + + _EqualAnyExpression(this.value, this.values); + + @override + String get name => 'equal_any'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'value': value.toMap(), + 'values': values.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a notEqualAny (NOT IN) function expression +class _NotEqualAnyExpression extends BooleanExpression { + final Expression value; + final List values; + + _NotEqualAnyExpression(this.value, this.values); + + @override + String get name => 'not_equal_any'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'value': value.toMap(), + 'values': values.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents an array expression +class _ArrayExpression extends FunctionExpression { + final List elements; + + _ArrayExpression(this.elements); + + @override + String get name => 'array'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'elements': elements.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a map expression +class _MapExpression extends FunctionExpression { + final Map data; + + _MapExpression(this.data); + + @override + String get name => 'map'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'data': data.map((k, v) => MapEntry(k, v.toMap())), + }, + }; + } +} + +/// Represents a mapFromPairs expression +class _MapFromPairsExpression extends FunctionExpression { + final List keyValuePairs; + + _MapFromPairsExpression(this.keyValuePairs); + + @override + String get name => 'map_from_pairs'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'pairs': keyValuePairs.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a raw function expression +class _RawFunctionExpression extends FunctionExpression { + final String functionName; + final List args; + + _RawFunctionExpression(this.functionName, this.args); + + @override + String get name => functionName; + + @override + Map toMap() { + return { + 'name': name, + 'args': args.map((expr) => expr.toMap()).toList(), + }; + } +} + +// ============================================================================ +// AGGREGATE FUNCTION CLASSES +// ============================================================================ + +/// Sums numeric values of the specified expression +class Sum extends PipelineAggregateFunction { + final Expression expression; + + Sum(this.expression); + + @override + String get name => 'sum'; @override Map toMap() { final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} - if (_andExpression != null) { - map['args'] = { - 'operator': 'and', - 'expressions': [_andExpression.toMap()], - }; - return map; - } +/// Calculates average of numeric values of the specified expression +class Average extends PipelineAggregateFunction { + final Expression expression; - if (_orExpression != null) { - map['args'] = { - 'operator': 'or', - 'expressions': [_orExpression.toMap()], - }; - return map; - } + Average(this.expression); - final args = {}; - if (field is String) { - args['field'] = field; - } else if (field is Field) { - args['field'] = (field as Field).fieldName; - } + @override + String get name => 'average'; - if (isEqualTo != null) args['isEqualTo'] = isEqualTo; - if (isNotEqualTo != null) args['isNotEqualTo'] = isNotEqualTo; - if (isLessThan != null) args['isLessThan'] = isLessThan; - if (isLessThanOrEqualTo != null) { - args['isLessThanOrEqualTo'] = isLessThanOrEqualTo; - } - if (isGreaterThan != null) args['isGreaterThan'] = isGreaterThan; - if (isGreaterThanOrEqualTo != null) { - args['isGreaterThanOrEqualTo'] = isGreaterThanOrEqualTo; - } - if (arrayContains != null) args['arrayContains'] = arrayContains; - if (arrayContainsAny != null) { - args['arrayContainsAny'] = arrayContainsAny; - } - if (whereIn != null) args['whereIn'] = whereIn; - if (whereNotIn != null) args['whereNotIn'] = whereNotIn; - if (isNull != null) args['isNull'] = isNull; - if (isNotNull != null) args['isNotNull'] = isNotNull; + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} - map['args'] = args; +/// Counts distinct values of the specified expression +class CountDistinct extends PipelineAggregateFunction { + final Expression expression; + + CountDistinct(this.expression); + + @override + String get name => 'count_distinct'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Finds minimum value of the specified expression +class Minimum extends PipelineAggregateFunction { + final Expression expression; + + Minimum(this.expression); + + @override + String get name => 'minimum'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Finds maximum value of the specified expression +class Maximum extends PipelineAggregateFunction { + final Expression expression; + + Maximum(this.expression); + + @override + String get name => 'maximum'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; return map; } } From 9ff80c6c960a4efd20ca8eb1287d496604e0fc9c Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Fri, 13 Feb 2026 11:17:58 +0000 Subject: [PATCH 5/5] chore: add support for Pigeon --- .../GeneratedAndroidFirebaseFirestore.java | 273 +++++- .../cloud_firestore/FirestoreMessages.g.m | 137 ++- .../Public/FirestoreMessages.g.h | 29 +- .../cloud_firestore/lib/src/firestore.dart | 1 + .../cloud_firestore/windows/messages.g.cpp | 177 +++- .../cloud_firestore/windows/messages.g.h | 72 +- .../method_channel_firestore.dart | 28 +- .../method_channel_pipeline_snapshot.dart | 15 +- .../lib/src/pigeon/messages.pigeon.dart | 409 ++++---- .../pigeons/messages.dart | 29 + .../test/pigeon/test_api.dart | 899 +++++++----------- 11 files changed, 1275 insertions(+), 794 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java index f7d24bc7c7ec..3638853507b6 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java @@ -12,6 +12,7 @@ import io.flutter.plugin.common.BasicMessageChannel; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MessageCodec; +import io.flutter.plugin.common.StandardMessageCodec; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -325,7 +326,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(5); toListResult.add(persistenceEnabled); toListResult.add(host); @@ -433,7 +434,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(3); toListResult.add(appName); toListResult.add((settings == null) ? null : settings.toList()); @@ -512,7 +513,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(2); toListResult.add(hasPendingWrites); toListResult.add(isFromCache); @@ -603,7 +604,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(3); toListResult.add(path); toListResult.add(data); @@ -724,7 +725,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(4); toListResult.add(type == null ? null : type.index); toListResult.add((document == null) ? null : document.toList()); @@ -833,7 +834,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(3); toListResult.add(documents); toListResult.add(documentChanges); @@ -856,6 +857,187 @@ public ArrayList toList() { } } + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonPipelineResult { + private @NonNull String documentPath; + + public @NonNull String getDocumentPath() { + return documentPath; + } + + public void setDocumentPath(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"documentPath\" is null."); + } + this.documentPath = setterArg; + } + + private @NonNull Long createTime; + + public @NonNull Long getCreateTime() { + return createTime; + } + + public void setCreateTime(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"createTime\" is null."); + } + this.createTime = setterArg; + } + + private @NonNull Long updateTime; + + public @NonNull Long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"updateTime\" is null."); + } + this.updateTime = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonPipelineResult() {} + + public static final class Builder { + + private @Nullable String documentPath; + + public @NonNull Builder setDocumentPath(@NonNull String setterArg) { + this.documentPath = setterArg; + return this; + } + + private @Nullable Long createTime; + + public @NonNull Builder setCreateTime(@NonNull Long setterArg) { + this.createTime = setterArg; + return this; + } + + private @Nullable Long updateTime; + + public @NonNull Builder setUpdateTime(@NonNull Long setterArg) { + this.updateTime = setterArg; + return this; + } + + public @NonNull PigeonPipelineResult build() { + PigeonPipelineResult pigeonReturn = new PigeonPipelineResult(); + pigeonReturn.setDocumentPath(documentPath); + pigeonReturn.setCreateTime(createTime); + pigeonReturn.setUpdateTime(updateTime); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(3); + toListResult.add(documentPath); + toListResult.add(createTime); + toListResult.add(updateTime); + return toListResult; + } + + static @NonNull PigeonPipelineResult fromList(@NonNull ArrayList list) { + PigeonPipelineResult pigeonResult = new PigeonPipelineResult(); + Object documentPath = list.get(0); + pigeonResult.setDocumentPath((String) documentPath); + Object createTime = list.get(1); + pigeonResult.setCreateTime( + (createTime == null) + ? null + : ((createTime instanceof Integer) ? (Integer) createTime : (Long) createTime)); + Object updateTime = list.get(2); + pigeonResult.setUpdateTime( + (updateTime == null) + ? null + : ((updateTime instanceof Integer) ? (Integer) updateTime : (Long) updateTime)); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonPipelineSnapshot { + private @NonNull List results; + + public @NonNull List getResults() { + return results; + } + + public void setResults(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"results\" is null."); + } + this.results = setterArg; + } + + private @NonNull Long executionTime; + + public @NonNull Long getExecutionTime() { + return executionTime; + } + + public void setExecutionTime(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"executionTime\" is null."); + } + this.executionTime = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonPipelineSnapshot() {} + + public static final class Builder { + + private @Nullable List results; + + public @NonNull Builder setResults(@NonNull List setterArg) { + this.results = setterArg; + return this; + } + + private @Nullable Long executionTime; + + public @NonNull Builder setExecutionTime(@NonNull Long setterArg) { + this.executionTime = setterArg; + return this; + } + + public @NonNull PigeonPipelineSnapshot build() { + PigeonPipelineSnapshot pigeonReturn = new PigeonPipelineSnapshot(); + pigeonReturn.setResults(results); + pigeonReturn.setExecutionTime(executionTime); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(results); + toListResult.add(executionTime); + return toListResult; + } + + static @NonNull PigeonPipelineSnapshot fromList(@NonNull ArrayList list) { + PigeonPipelineSnapshot pigeonResult = new PigeonPipelineSnapshot(); + Object results = list.get(0); + pigeonResult.setResults((List) results); + Object executionTime = list.get(1); + pigeonResult.setExecutionTime( + (executionTime == null) + ? null + : ((executionTime instanceof Integer) + ? (Integer) executionTime + : (Long) executionTime)); + return pigeonResult; + } + } + /** Generated class from Pigeon that represents data sent in messages. */ public static final class PigeonGetOptions { private @NonNull Source source; @@ -913,7 +1095,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(2); toListResult.add(source == null ? null : source.index); toListResult.add(serverTimestampBehavior == null ? null : serverTimestampBehavior.index); @@ -978,7 +1160,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(2); toListResult.add(merge); toListResult.add(mergeFields); @@ -1087,7 +1269,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(4); toListResult.add(type == null ? null : type.index); toListResult.add(path); @@ -1219,7 +1401,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(5); toListResult.add(path); toListResult.add(data); @@ -1422,7 +1604,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(9); toListResult.add(where); toListResult.add(orderBy); @@ -1517,7 +1699,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(2); toListResult.add(type == null ? null : type.index); toListResult.add(field); @@ -1605,7 +1787,7 @@ public static final class Builder { } @NonNull - public ArrayList toList() { + ArrayList toList() { ArrayList toListResult = new ArrayList(3); toListResult.add(type == null ? null : type.index); toListResult.add(field); @@ -1632,7 +1814,7 @@ public interface Result { void error(@NonNull Throwable error); } - private static class FirebaseFirestoreHostApiCodec extends FlutterFirebaseFirestoreMessageCodec { + private static class FirebaseFirestoreHostApiCodec extends StandardMessageCodec { public static final FirebaseFirestoreHostApiCodec INSTANCE = new FirebaseFirestoreHostApiCodec(); @@ -1660,12 +1842,16 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { case (byte) 136: return PigeonGetOptions.fromList((ArrayList) readValue(buffer)); case (byte) 137: - return PigeonQueryParameters.fromList((ArrayList) readValue(buffer)); + return PigeonPipelineResult.fromList((ArrayList) readValue(buffer)); case (byte) 138: - return PigeonQuerySnapshot.fromList((ArrayList) readValue(buffer)); + return PigeonPipelineSnapshot.fromList((ArrayList) readValue(buffer)); case (byte) 139: - return PigeonSnapshotMetadata.fromList((ArrayList) readValue(buffer)); + return PigeonQueryParameters.fromList((ArrayList) readValue(buffer)); case (byte) 140: + return PigeonQuerySnapshot.fromList((ArrayList) readValue(buffer)); + case (byte) 141: + return PigeonSnapshotMetadata.fromList((ArrayList) readValue(buffer)); + case (byte) 142: return PigeonTransactionCommand.fromList((ArrayList) readValue(buffer)); default: return super.readValueOfType(type, buffer); @@ -1701,17 +1887,23 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { } else if (value instanceof PigeonGetOptions) { stream.write(136); writeValue(stream, ((PigeonGetOptions) value).toList()); - } else if (value instanceof PigeonQueryParameters) { + } else if (value instanceof PigeonPipelineResult) { stream.write(137); + writeValue(stream, ((PigeonPipelineResult) value).toList()); + } else if (value instanceof PigeonPipelineSnapshot) { + stream.write(138); + writeValue(stream, ((PigeonPipelineSnapshot) value).toList()); + } else if (value instanceof PigeonQueryParameters) { + stream.write(139); writeValue(stream, ((PigeonQueryParameters) value).toList()); } else if (value instanceof PigeonQuerySnapshot) { - stream.write(138); + stream.write(140); writeValue(stream, ((PigeonQuerySnapshot) value).toList()); } else if (value instanceof PigeonSnapshotMetadata) { - stream.write(139); + stream.write(141); writeValue(stream, ((PigeonSnapshotMetadata) value).toList()); } else if (value instanceof PigeonTransactionCommand) { - stream.write(140); + stream.write(142); writeValue(stream, ((PigeonTransactionCommand) value).toList()); } else { super.writeValue(stream, value); @@ -1836,6 +2028,12 @@ void persistenceCacheIndexManagerRequest( @NonNull PersistenceCacheIndexManagerRequest request, @NonNull Result result); + void executePipeline( + @NonNull FirestorePigeonFirebaseApp app, + @NonNull List> stages, + @Nullable Map options, + @NonNull Result result); + /** The codec used by FirebaseFirestoreHostApi. */ static @NonNull MessageCodec getCodec() { return FirebaseFirestoreHostApiCodec.INSTANCE; @@ -2624,6 +2822,39 @@ public void error(Throwable error) { channel.setMessageHandler(null); } } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); + List> stagesArg = (List>) args.get(1); + Map optionsArg = (Map) args.get(2); + Result resultCallback = + new Result() { + public void success(PigeonPipelineSnapshot result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.executePipeline(appArg, stagesArg, optionsArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } } } } diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m index 34e717b694a7..2818f5742f4b 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m @@ -5,8 +5,6 @@ // See also: https://pub.dev/packages/pigeon #import "FirestoreMessages.g.h" -#import "FLTFirebaseFirestoreReader.h" -#import "FLTFirebaseFirestoreWriter.h" #if TARGET_OS_OSX #import @@ -168,6 +166,18 @@ + (nullable PigeonQuerySnapshot *)nullableFromList:(NSArray *)list; - (NSArray *)toList; @end +@interface PigeonPipelineResult () ++ (PigeonPipelineResult *)fromList:(NSArray *)list; ++ (nullable PigeonPipelineResult *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonPipelineSnapshot () ++ (PigeonPipelineSnapshot *)fromList:(NSArray *)list; ++ (nullable PigeonPipelineSnapshot *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + @interface PigeonGetOptions () + (PigeonGetOptions *)fromList:(NSArray *)list; + (nullable PigeonGetOptions *)nullableFromList:(NSArray *)list; @@ -349,7 +359,7 @@ + (instancetype)makeWithType:(DocumentChangeType)type pigeonResult.type = type; pigeonResult.document = document; pigeonResult.oldIndex = oldIndex; - pigeonResult.index = newIndex; + pigeonResult.newIndex = newIndex; return pigeonResult; } + (PigeonDocumentChange *)fromList:(NSArray *)list { @@ -360,8 +370,8 @@ + (PigeonDocumentChange *)fromList:(NSArray *)list { NSAssert(pigeonResult.document != nil, @""); pigeonResult.oldIndex = GetNullableObjectAtIndex(list, 2); NSAssert(pigeonResult.oldIndex != nil, @""); - pigeonResult.index = GetNullableObjectAtIndex(list, 3); - NSAssert(pigeonResult.index != nil, @""); + pigeonResult.newIndex = GetNullableObjectAtIndex(list, 3); + NSAssert(pigeonResult.newIndex != nil, @""); return pigeonResult; } + (nullable PigeonDocumentChange *)nullableFromList:(NSArray *)list { @@ -372,7 +382,7 @@ - (NSArray *)toList { @(self.type), (self.document ? [self.document toList] : [NSNull null]), (self.oldIndex ?: [NSNull null]), - (self.index ?: [NSNull null]), + (self.newIndex ?: [NSNull null]), ]; } @end @@ -410,6 +420,65 @@ - (NSArray *)toList { } @end +@implementation PigeonPipelineResult ++ (instancetype)makeWithDocumentPath:(NSString *)documentPath + createTime:(NSNumber *)createTime + updateTime:(NSNumber *)updateTime { + PigeonPipelineResult *pigeonResult = [[PigeonPipelineResult alloc] init]; + pigeonResult.documentPath = documentPath; + pigeonResult.createTime = createTime; + pigeonResult.updateTime = updateTime; + return pigeonResult; +} ++ (PigeonPipelineResult *)fromList:(NSArray *)list { + PigeonPipelineResult *pigeonResult = [[PigeonPipelineResult alloc] init]; + pigeonResult.documentPath = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.documentPath != nil, @""); + pigeonResult.createTime = GetNullableObjectAtIndex(list, 1); + NSAssert(pigeonResult.createTime != nil, @""); + pigeonResult.updateTime = GetNullableObjectAtIndex(list, 2); + NSAssert(pigeonResult.updateTime != nil, @""); + return pigeonResult; +} ++ (nullable PigeonPipelineResult *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonPipelineResult fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.documentPath ?: [NSNull null]), + (self.createTime ?: [NSNull null]), + (self.updateTime ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonPipelineSnapshot ++ (instancetype)makeWithResults:(NSArray *)results + executionTime:(NSNumber *)executionTime { + PigeonPipelineSnapshot *pigeonResult = [[PigeonPipelineSnapshot alloc] init]; + pigeonResult.results = results; + pigeonResult.executionTime = executionTime; + return pigeonResult; +} ++ (PigeonPipelineSnapshot *)fromList:(NSArray *)list { + PigeonPipelineSnapshot *pigeonResult = [[PigeonPipelineSnapshot alloc] init]; + pigeonResult.results = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.results != nil, @""); + pigeonResult.executionTime = GetNullableObjectAtIndex(list, 1); + NSAssert(pigeonResult.executionTime != nil, @""); + return pigeonResult; +} ++ (nullable PigeonPipelineSnapshot *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonPipelineSnapshot fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.results ?: [NSNull null]), + (self.executionTime ?: [NSNull null]), + ]; +} +@end + @implementation PigeonGetOptions + (instancetype)makeWithSource:(Source)source serverTimestampBehavior:(ServerTimestampBehavior)serverTimestampBehavior { @@ -649,7 +718,7 @@ - (NSArray *)toList { } @end -@interface FirebaseFirestoreHostApiCodecReader : FLTFirebaseFirestoreReader +@interface FirebaseFirestoreHostApiCodecReader : FlutterStandardReader @end @implementation FirebaseFirestoreHostApiCodecReader - (nullable id)readValueOfType:(UInt8)type { @@ -673,12 +742,16 @@ - (nullable id)readValueOfType:(UInt8)type { case 136: return [PigeonGetOptions fromList:[self readValue]]; case 137: - return [PigeonQueryParameters fromList:[self readValue]]; + return [PigeonPipelineResult fromList:[self readValue]]; case 138: - return [PigeonQuerySnapshot fromList:[self readValue]]; + return [PigeonPipelineSnapshot fromList:[self readValue]]; case 139: - return [PigeonSnapshotMetadata fromList:[self readValue]]; + return [PigeonQueryParameters fromList:[self readValue]]; case 140: + return [PigeonQuerySnapshot fromList:[self readValue]]; + case 141: + return [PigeonSnapshotMetadata fromList:[self readValue]]; + case 142: return [PigeonTransactionCommand fromList:[self readValue]]; default: return [super readValueOfType:type]; @@ -686,7 +759,7 @@ - (nullable id)readValueOfType:(UInt8)type { } @end -@interface FirebaseFirestoreHostApiCodecWriter : FLTFirebaseFirestoreWriter +@interface FirebaseFirestoreHostApiCodecWriter : FlutterStandardWriter @end @implementation FirebaseFirestoreHostApiCodecWriter - (void)writeValue:(id)value { @@ -717,18 +790,24 @@ - (void)writeValue:(id)value { } else if ([value isKindOfClass:[PigeonGetOptions class]]) { [self writeByte:136]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonQueryParameters class]]) { + } else if ([value isKindOfClass:[PigeonPipelineResult class]]) { [self writeByte:137]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonQuerySnapshot class]]) { + } else if ([value isKindOfClass:[PigeonPipelineSnapshot class]]) { [self writeByte:138]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonSnapshotMetadata class]]) { + } else if ([value isKindOfClass:[PigeonQueryParameters class]]) { [self writeByte:139]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonTransactionCommand class]]) { + } else if ([value isKindOfClass:[PigeonQuerySnapshot class]]) { [self writeByte:140]; [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonSnapshotMetadata class]]) { + [self writeByte:141]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonTransactionCommand class]]) { + [self writeByte:142]; + [self writeValue:[value toList]]; } else { [super writeValue:value]; } @@ -1379,4 +1458,32 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, [channel setMessageHandler:nil]; } } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.executePipeline" + binaryMessenger:binaryMessenger + codec:FirebaseFirestoreHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(executePipelineApp:stages:options:completion:)], + @"FirebaseFirestoreHostApi api (%@) doesn't respond to " + @"@selector(executePipelineApp:stages:options:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSArray *> *arg_stages = GetNullableObjectAtIndex(args, 1); + NSDictionary *arg_options = GetNullableObjectAtIndex(args, 2); + [api executePipelineApp:arg_app + stages:arg_stages + options:arg_options + completion:^(PigeonPipelineSnapshot *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } } diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h index 2eabaeaef25f..1f43fa87bf89 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h @@ -165,6 +165,8 @@ typedef NS_ENUM(NSUInteger, AggregateType) { @class PigeonDocumentSnapshot; @class PigeonDocumentChange; @class PigeonQuerySnapshot; +@class PigeonPipelineResult; +@class PigeonPipelineSnapshot; @class PigeonGetOptions; @class PigeonDocumentOption; @class PigeonTransactionCommand; @@ -229,7 +231,7 @@ typedef NS_ENUM(NSUInteger, AggregateType) { @property(nonatomic, assign) DocumentChangeType type; @property(nonatomic, strong) PigeonDocumentSnapshot *document; @property(nonatomic, strong) NSNumber *oldIndex; -@property(nonatomic, strong) NSNumber *index; +@property(nonatomic, strong) NSNumber *newIndex; @end @interface PigeonQuerySnapshot : NSObject @@ -243,6 +245,26 @@ typedef NS_ENUM(NSUInteger, AggregateType) { @property(nonatomic, strong) PigeonSnapshotMetadata *metadata; @end +@interface PigeonPipelineResult : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithDocumentPath:(NSString *)documentPath + createTime:(NSNumber *)createTime + updateTime:(NSNumber *)updateTime; +@property(nonatomic, copy) NSString *documentPath; +@property(nonatomic, strong) NSNumber *createTime; +@property(nonatomic, strong) NSNumber *updateTime; +@end + +@interface PigeonPipelineSnapshot : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithResults:(NSArray *)results + executionTime:(NSNumber *)executionTime; +@property(nonatomic, strong) NSArray *results; +@property(nonatomic, strong) NSNumber *executionTime; +@end + @interface PigeonGetOptions : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; @@ -416,6 +438,11 @@ NSObject *FirebaseFirestoreHostApiGetCodec(void); - (void)persistenceCacheIndexManagerRequestApp:(FirestorePigeonFirebaseApp *)app request:(PersistenceCacheIndexManagerRequest)request completion:(void (^)(FlutterError *_Nullable))completion; +- (void)executePipelineApp:(FirestorePigeonFirebaseApp *)app + stages:(NSArray *> *)stages + options:(nullable NSDictionary *)options + completion:(void (^)(PigeonPipelineSnapshot *_Nullable, + FlutterError *_Nullable))completion; @end extern void FirebaseFirestoreHostApiSetup(id binaryMessenger, diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart index 3e583c3f3331..32fe4f3e16db 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart @@ -354,6 +354,7 @@ class FirebaseFirestore extends FirebasePluginPlatform { /// .limit(10) /// .execute(); /// ``` + // ignore: use_to_and_as_if_applicable PipelineSource pipeline() { return PipelineSource._(this); } diff --git a/packages/cloud_firestore/cloud_firestore/windows/messages.g.cpp b/packages/cloud_firestore/cloud_firestore/windows/messages.g.cpp index bb9f58d5775d..a70d4a7b95d5 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/messages.g.cpp +++ b/packages/cloud_firestore/cloud_firestore/windows/messages.g.cpp @@ -397,6 +397,88 @@ PigeonQuerySnapshot PigeonQuerySnapshot::FromEncodableList( return decoded; } +// PigeonPipelineResult + +PigeonPipelineResult::PigeonPipelineResult(const std::string& document_path, + int64_t create_time, + int64_t update_time) + : document_path_(document_path), + create_time_(create_time), + update_time_(update_time) {} + +const std::string& PigeonPipelineResult::document_path() const { + return document_path_; +} + +void PigeonPipelineResult::set_document_path(std::string_view value_arg) { + document_path_ = value_arg; +} + +int64_t PigeonPipelineResult::create_time() const { return create_time_; } + +void PigeonPipelineResult::set_create_time(int64_t value_arg) { + create_time_ = value_arg; +} + +int64_t PigeonPipelineResult::update_time() const { return update_time_; } + +void PigeonPipelineResult::set_update_time(int64_t value_arg) { + update_time_ = value_arg; +} + +EncodableList PigeonPipelineResult::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(EncodableValue(document_path_)); + list.push_back(EncodableValue(create_time_)); + list.push_back(EncodableValue(update_time_)); + return list; +} + +PigeonPipelineResult PigeonPipelineResult::FromEncodableList( + const EncodableList& list) { + PigeonPipelineResult decoded(std::get(list[0]), + list[1].LongValue(), list[2].LongValue()); + return decoded; +} + +// PigeonPipelineSnapshot + +PigeonPipelineSnapshot::PigeonPipelineSnapshot(const EncodableList& results, + int64_t execution_time) + : results_(results), execution_time_(execution_time) {} + +const EncodableList& PigeonPipelineSnapshot::results() const { + return results_; +} + +void PigeonPipelineSnapshot::set_results(const EncodableList& value_arg) { + results_ = value_arg; +} + +int64_t PigeonPipelineSnapshot::execution_time() const { + return execution_time_; +} + +void PigeonPipelineSnapshot::set_execution_time(int64_t value_arg) { + execution_time_ = value_arg; +} + +EncodableList PigeonPipelineSnapshot::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(results_)); + list.push_back(EncodableValue(execution_time_)); + return list; +} + +PigeonPipelineSnapshot PigeonPipelineSnapshot::FromEncodableList( + const EncodableList& list) { + PigeonPipelineSnapshot decoded(std::get(list[0]), + list[1].LongValue()); + return decoded; +} + // PigeonGetOptions PigeonGetOptions::PigeonGetOptions( @@ -1034,20 +1116,25 @@ EncodableValue FirebaseFirestoreHostApiCodecSerializer::ReadValueOfType( return CustomEncodableValue(PigeonGetOptions::FromEncodableList( std::get(ReadValue(stream)))); case 137: - return CustomEncodableValue(PigeonQueryParameters::FromEncodableList( + return CustomEncodableValue(PigeonPipelineResult::FromEncodableList( std::get(ReadValue(stream)))); case 138: - return CustomEncodableValue(PigeonQuerySnapshot::FromEncodableList( + return CustomEncodableValue(PigeonPipelineSnapshot::FromEncodableList( std::get(ReadValue(stream)))); case 139: - return CustomEncodableValue(PigeonSnapshotMetadata::FromEncodableList( + return CustomEncodableValue(PigeonQueryParameters::FromEncodableList( std::get(ReadValue(stream)))); case 140: + return CustomEncodableValue(PigeonQuerySnapshot::FromEncodableList( + std::get(ReadValue(stream)))); + case 141: + return CustomEncodableValue(PigeonSnapshotMetadata::FromEncodableList( + std::get(ReadValue(stream)))); + case 142: return CustomEncodableValue(PigeonTransactionCommand::FromEncodableList( std::get(ReadValue(stream)))); default: - return cloud_firestore_windows::FirestoreCodec::ReadValueOfType(type, - stream); + return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } } @@ -1127,8 +1214,24 @@ void FirebaseFirestoreHostApiCodecSerializer::WriteValue( stream); return; } - if (custom_value->type() == typeid(PigeonQueryParameters)) { + if (custom_value->type() == typeid(PigeonPipelineResult)) { stream->WriteByte(137); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(PigeonPipelineSnapshot)) { + stream->WriteByte(138); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(PigeonQueryParameters)) { + stream->WriteByte(139); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), @@ -1136,7 +1239,7 @@ void FirebaseFirestoreHostApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PigeonQuerySnapshot)) { - stream->WriteByte(138); + stream->WriteByte(140); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), @@ -1144,7 +1247,7 @@ void FirebaseFirestoreHostApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PigeonSnapshotMetadata)) { - stream->WriteByte(139); + stream->WriteByte(141); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), @@ -1152,7 +1255,7 @@ void FirebaseFirestoreHostApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PigeonTransactionCommand)) { - stream->WriteByte(140); + stream->WriteByte(142); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), @@ -1160,7 +1263,7 @@ void FirebaseFirestoreHostApiCodecSerializer::WriteValue( return; } } - cloud_firestore_windows::FirestoreCodec::WriteValue(value, stream); + flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseFirestoreHostApi. @@ -2290,8 +2393,8 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("request_arg unexpectedly null.")); return; } - const PersistenceCacheIndexManagerRequestEnum& request_arg = - (PersistenceCacheIndexManagerRequestEnum) + const PersistenceCacheIndexManagerRequest& request_arg = + (PersistenceCacheIndexManagerRequest) encodable_request_arg.LongValue(); api->PersistenceCacheIndexManagerRequest( app_arg, request_arg, @@ -2312,6 +2415,56 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, channel->SetMessageHandler(nullptr); } } + { + auto channel = std::make_unique>( + binary_messenger, + "dev.flutter.pigeon.cloud_firestore_platform_interface." + "FirebaseFirestoreHostApi.executePipeline", + &GetCodec()); + if (api != nullptr) { + channel->SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = + std::any_cast( + std::get(encodable_app_arg)); + const auto& encodable_stages_arg = args.at(1); + if (encodable_stages_arg.IsNull()) { + reply(WrapError("stages_arg unexpectedly null.")); + return; + } + const auto& stages_arg = + std::get(encodable_stages_arg); + const auto& encodable_options_arg = args.at(2); + const auto* options_arg = + std::get_if(&encodable_options_arg); + api->ExecutePipeline( + app_arg, stages_arg, options_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel->SetMessageHandler(nullptr); + } + } } EncodableValue FirebaseFirestoreHostApi::WrapError( diff --git a/packages/cloud_firestore/cloud_firestore/windows/messages.g.h b/packages/cloud_firestore/cloud_firestore/windows/messages.g.h index 8aecb887facc..40e4369d79d8 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/messages.g.h +++ b/packages/cloud_firestore/cloud_firestore/windows/messages.g.h @@ -15,8 +15,6 @@ #include #include -#include "firestore_codec.h" - namespace cloud_firestore_windows { // Generated class from Pigeon. @@ -136,7 +134,7 @@ enum class AggregateSource { // [PersistenceCacheIndexManagerRequest] represents the request types for the // persistence cache index manager. -enum class PersistenceCacheIndexManagerRequestEnum { +enum class PersistenceCacheIndexManagerRequest { enableIndexAutoCreation = 0, disableIndexAutoCreation = 1, deleteAllIndexes = 2 @@ -239,11 +237,10 @@ class PigeonSnapshotMetadata { bool is_from_cache() const; void set_is_from_cache(bool value_arg); + private: static PigeonSnapshotMetadata FromEncodableList( const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; - - private: friend class PigeonDocumentSnapshot; friend class PigeonQuerySnapshot; friend class FirebaseFirestoreHostApi; @@ -274,11 +271,10 @@ class PigeonDocumentSnapshot { const PigeonSnapshotMetadata& metadata() const; void set_metadata(const PigeonSnapshotMetadata& value_arg); + private: static PigeonDocumentSnapshot FromEncodableList( const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; - - private: friend class PigeonDocumentChange; friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; @@ -307,11 +303,10 @@ class PigeonDocumentChange { int64_t new_index() const; void set_new_index(int64_t value_arg); + private: static PigeonDocumentChange FromEncodableList( const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; - - private: friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; DocumentChangeType type_; @@ -348,6 +343,56 @@ class PigeonQuerySnapshot { PigeonSnapshotMetadata metadata_; }; +// Generated class from Pigeon that represents data sent in messages. +class PigeonPipelineResult { + public: + // Constructs an object setting all fields. + explicit PigeonPipelineResult(const std::string& document_path, + int64_t create_time, int64_t update_time); + + const std::string& document_path() const; + void set_document_path(std::string_view value_arg); + + int64_t create_time() const; + void set_create_time(int64_t value_arg); + + int64_t update_time() const; + void set_update_time(int64_t value_arg); + + private: + static PigeonPipelineResult FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseFirestoreHostApi; + friend class FirebaseFirestoreHostApiCodecSerializer; + std::string document_path_; + int64_t create_time_; + int64_t update_time_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class PigeonPipelineSnapshot { + public: + // Constructs an object setting all fields. + explicit PigeonPipelineSnapshot(const flutter::EncodableList& results, + int64_t execution_time); + + const flutter::EncodableList& results() const; + void set_results(const flutter::EncodableList& value_arg); + + int64_t execution_time() const; + void set_execution_time(int64_t value_arg); + + private: + static PigeonPipelineSnapshot FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseFirestoreHostApi; + friend class FirebaseFirestoreHostApiCodecSerializer; + flutter::EncodableList results_; + int64_t execution_time_; +}; + // Generated class from Pigeon that represents data sent in messages. class PigeonGetOptions { public: @@ -613,7 +658,7 @@ class AggregateQueryResponse { }; class FirebaseFirestoreHostApiCodecSerializer - : public cloud_firestore_windows::FirestoreCodec { + : public flutter::StandardCodecSerializer { public: FirebaseFirestoreHostApiCodecSerializer(); inline static FirebaseFirestoreHostApiCodecSerializer& GetInstance() { @@ -724,8 +769,13 @@ class FirebaseFirestoreHostApi { std::function reply)> result) = 0; virtual void PersistenceCacheIndexManagerRequest( const FirestorePigeonFirebaseApp& app, - const PersistenceCacheIndexManagerRequestEnum& request, + const PersistenceCacheIndexManagerRequest& request, std::function reply)> result) = 0; + virtual void ExecutePipeline( + const FirestorePigeonFirebaseApp& app, + const flutter::EncodableList& stages, + const flutter::EncodableMap* options, + std::function reply)> result) = 0; // The codec used by FirebaseFirestoreHostApi. static const flutter::StandardMessageCodec& GetCodec(); diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart index 73aacc45f2bb..889ea4c5351b 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart @@ -364,21 +364,25 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { Map? options, }) async { try { - final MethodChannel channel = const MethodChannel( - 'plugins.flutter.io/firebase_firestore', + // Convert stages to Pigeon format (List?>) + final List?> pigeonStages = stages.map((stage) { + return stage.map(MapEntry.new); + }).toList(); + + // Convert options to Pigeon format (Map?) + final Map? pigeonOptions = options?.map( + MapEntry.new, ); - final result = await channel.invokeMethod>( - 'Pipeline#execute', - { - 'app': pigeonApp, - 'stages': stages, - if (options != null) 'options': options, - }, + + final PigeonPipelineSnapshot result = await pigeonChannel.executePipeline( + pigeonApp, + pigeonStages, + pigeonOptions, ); - return MethodChannelPipelineSnapshot(this, pigeonApp, result!); - } on PlatformException catch (e, stack) { - throw convertPlatformException(e, stack); + return MethodChannelPipelineSnapshot(this, pigeonApp, result); + } catch (e, stack) { + convertPlatformException(e, stack); } } } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart index 16cde78be465..51ff99ffcff9 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart @@ -12,22 +12,23 @@ class MethodChannelPipelineSnapshot extends PipelineSnapshotPlatform { final List _results; final DateTime _executionTime; - /// Creates a [MethodChannelPipelineSnapshot] from the given [data] + /// Creates a [MethodChannelPipelineSnapshot] from the given [pigeonSnapshot] MethodChannelPipelineSnapshot( FirebaseFirestorePlatform firestore, FirestorePigeonFirebaseApp pigeonApp, - Map data, - ) : _results = (data['results'] as List) + PigeonPipelineSnapshot pigeonSnapshot, + ) : _results = (pigeonSnapshot.results ?? []) + .whereType() .map((result) => MethodChannelPipelineResult( firestore, pigeonApp, - result['document'] as String, - DateTime.fromMillisecondsSinceEpoch(result['createTime']), - DateTime.fromMillisecondsSinceEpoch(result['updateTime']), + result.documentPath, + DateTime.fromMillisecondsSinceEpoch(result.createTime), + DateTime.fromMillisecondsSinceEpoch(result.updateTime), )) .toList(), _executionTime = DateTime.fromMillisecondsSinceEpoch( - data['executionTime'] as int, + pigeonSnapshot.executionTime, ), super(); diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart index 85af6edc5260..0ea2ee91ccd5 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -8,7 +8,6 @@ import 'dart:async'; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart'; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; @@ -301,6 +300,63 @@ class PigeonQuerySnapshot { } } +class PigeonPipelineResult { + PigeonPipelineResult({ + required this.documentPath, + required this.createTime, + required this.updateTime, + }); + + String documentPath; + + int createTime; + + int updateTime; + + Object encode() { + return [ + documentPath, + createTime, + updateTime, + ]; + } + + static PigeonPipelineResult decode(Object result) { + result as List; + return PigeonPipelineResult( + documentPath: result[0]! as String, + createTime: result[1]! as int, + updateTime: result[2]! as int, + ); + } +} + +class PigeonPipelineSnapshot { + PigeonPipelineSnapshot({ + required this.results, + required this.executionTime, + }); + + List results; + + int executionTime; + + Object encode() { + return [ + results, + executionTime, + ]; + } + + static PigeonPipelineSnapshot decode(Object result) { + result as List; + return PigeonPipelineSnapshot( + results: (result[0] as List?)!.cast(), + executionTime: result[1]! as int, + ); + } +} + class PigeonGetOptions { PigeonGetOptions({ required this.source, @@ -555,7 +611,7 @@ class AggregateQueryResponse { } } -class _FirebaseFirestoreHostApiCodec extends FirestoreMessageCodec { +class _FirebaseFirestoreHostApiCodec extends StandardMessageCodec { const _FirebaseFirestoreHostApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { @@ -586,18 +642,24 @@ class _FirebaseFirestoreHostApiCodec extends FirestoreMessageCodec { } else if (value is PigeonGetOptions) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is PigeonQueryParameters) { + } else if (value is PigeonPipelineResult) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is PigeonQuerySnapshot) { + } else if (value is PigeonPipelineSnapshot) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PigeonSnapshotMetadata) { + } else if (value is PigeonQueryParameters) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PigeonTransactionCommand) { + } else if (value is PigeonQuerySnapshot) { buffer.putUint8(140); writeValue(buffer, value.encode()); + } else if (value is PigeonSnapshotMetadata) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PigeonTransactionCommand) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -625,12 +687,16 @@ class _FirebaseFirestoreHostApiCodec extends FirestoreMessageCodec { case 136: return PigeonGetOptions.decode(readValue(buffer)!); case 137: - return PigeonQueryParameters.decode(readValue(buffer)!); + return PigeonPipelineResult.decode(readValue(buffer)!); case 138: - return PigeonQuerySnapshot.decode(readValue(buffer)!); + return PigeonPipelineSnapshot.decode(readValue(buffer)!); case 139: - return PigeonSnapshotMetadata.decode(readValue(buffer)!); + return PigeonQueryParameters.decode(readValue(buffer)!); case 140: + return PigeonQuerySnapshot.decode(readValue(buffer)!); + case 141: + return PigeonSnapshotMetadata.decode(readValue(buffer)!); + case 142: return PigeonTransactionCommand.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -649,14 +715,11 @@ class FirebaseFirestoreHostApi { static const MessageCodec codec = _FirebaseFirestoreHostApiCodec(); Future loadBundle( - FirestorePigeonFirebaseApp arg_app, - Uint8List arg_bundle, - ) async { + FirestorePigeonFirebaseApp arg_app, Uint8List arg_bundle) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app, arg_bundle]) as List?; if (replyList == null) { @@ -680,16 +743,12 @@ class FirebaseFirestoreHostApi { } } - Future namedQueryGet( - FirestorePigeonFirebaseApp arg_app, - String arg_name, - PigeonGetOptions arg_options, - ) async { + Future namedQueryGet(FirestorePigeonFirebaseApp arg_app, + String arg_name, PigeonGetOptions arg_options) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel .send([arg_app, arg_name, arg_options]) as List?; if (replyList == null) { @@ -715,10 +774,9 @@ class FirebaseFirestoreHostApi { Future clearPersistence(FirestorePigeonFirebaseApp arg_app) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app]) as List?; if (replyList == null) { @@ -739,10 +797,9 @@ class FirebaseFirestoreHostApi { Future disableNetwork(FirestorePigeonFirebaseApp arg_app) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app]) as List?; if (replyList == null) { @@ -763,10 +820,9 @@ class FirebaseFirestoreHostApi { Future enableNetwork(FirestorePigeonFirebaseApp arg_app) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app]) as List?; if (replyList == null) { @@ -787,10 +843,9 @@ class FirebaseFirestoreHostApi { Future terminate(FirestorePigeonFirebaseApp arg_app) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app]) as List?; if (replyList == null) { @@ -811,10 +866,9 @@ class FirebaseFirestoreHostApi { Future waitForPendingWrites(FirestorePigeonFirebaseApp arg_app) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app]) as List?; if (replyList == null) { @@ -834,14 +888,11 @@ class FirebaseFirestoreHostApi { } Future setIndexConfiguration( - FirestorePigeonFirebaseApp arg_app, - String arg_indexConfiguration, - ) async { + FirestorePigeonFirebaseApp arg_app, String arg_indexConfiguration) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel .send([arg_app, arg_indexConfiguration]) as List?; if (replyList == null) { @@ -862,10 +913,9 @@ class FirebaseFirestoreHostApi { Future setLoggingEnabled(bool arg_loggingEnabled) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_loggingEnabled]) as List?; if (replyList == null) { @@ -885,13 +935,11 @@ class FirebaseFirestoreHostApi { } Future snapshotsInSyncSetup( - FirestorePigeonFirebaseApp arg_app, - ) async { + FirestorePigeonFirebaseApp arg_app) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app]) as List?; if (replyList == null) { @@ -915,16 +963,12 @@ class FirebaseFirestoreHostApi { } } - Future transactionCreate( - FirestorePigeonFirebaseApp arg_app, - int arg_timeout, - int arg_maxAttempts, - ) async { + Future transactionCreate(FirestorePigeonFirebaseApp arg_app, + int arg_timeout, int arg_maxAttempts) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app, arg_timeout, arg_maxAttempts]) as List?; @@ -950,18 +994,16 @@ class FirebaseFirestoreHostApi { } Future transactionStoreResult( - String arg_transactionId, - PigeonTransactionResult arg_resultType, - List? arg_commands, - ) async { + String arg_transactionId, + PigeonTransactionResult arg_resultType, + List? arg_commands) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send( - [arg_transactionId, arg_resultType.index, arg_commands], - ) as List?; + [arg_transactionId, arg_resultType.index, arg_commands]) + as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -979,15 +1021,13 @@ class FirebaseFirestoreHostApi { } Future transactionGet( - FirestorePigeonFirebaseApp arg_app, - String arg_transactionId, - String arg_path, - ) async { + FirestorePigeonFirebaseApp arg_app, + String arg_transactionId, + String arg_path) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app, arg_transactionId, arg_path]) as List?; @@ -1012,15 +1052,12 @@ class FirebaseFirestoreHostApi { } } - Future documentReferenceSet( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_request, - ) async { + Future documentReferenceSet(FirestorePigeonFirebaseApp arg_app, + DocumentReferenceRequest arg_request) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app, arg_request]) as List?; if (replyList == null) { @@ -1039,15 +1076,12 @@ class FirebaseFirestoreHostApi { } } - Future documentReferenceUpdate( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_request, - ) async { + Future documentReferenceUpdate(FirestorePigeonFirebaseApp arg_app, + DocumentReferenceRequest arg_request) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app, arg_request]) as List?; if (replyList == null) { @@ -1067,14 +1101,12 @@ class FirebaseFirestoreHostApi { } Future documentReferenceGet( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_request, - ) async { + FirestorePigeonFirebaseApp arg_app, + DocumentReferenceRequest arg_request) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app, arg_request]) as List?; if (replyList == null) { @@ -1098,15 +1130,12 @@ class FirebaseFirestoreHostApi { } } - Future documentReferenceDelete( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_request, - ) async { + Future documentReferenceDelete(FirestorePigeonFirebaseApp arg_app, + DocumentReferenceRequest arg_request) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app, arg_request]) as List?; if (replyList == null) { @@ -1126,23 +1155,21 @@ class FirebaseFirestoreHostApi { } Future queryGet( - FirestorePigeonFirebaseApp arg_app, - String arg_path, - bool arg_isCollectionGroup, - PigeonQueryParameters arg_parameters, - PigeonGetOptions arg_options, - ) async { + FirestorePigeonFirebaseApp arg_app, + String arg_path, + bool arg_isCollectionGroup, + PigeonQueryParameters arg_parameters, + PigeonGetOptions arg_options) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([ arg_app, arg_path, arg_isCollectionGroup, arg_parameters, - arg_options, + arg_options ]) as List?; if (replyList == null) { throw PlatformException( @@ -1166,25 +1193,23 @@ class FirebaseFirestoreHostApi { } Future> aggregateQuery( - FirestorePigeonFirebaseApp arg_app, - String arg_path, - PigeonQueryParameters arg_parameters, - AggregateSource arg_source, - List arg_queries, - bool arg_isCollectionGroup, - ) async { + FirestorePigeonFirebaseApp arg_app, + String arg_path, + PigeonQueryParameters arg_parameters, + AggregateSource arg_source, + List arg_queries, + bool arg_isCollectionGroup) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([ arg_app, arg_path, arg_parameters, arg_source.index, arg_queries, - arg_isCollectionGroup, + arg_isCollectionGroup ]) as List?; if (replyList == null) { throw PlatformException( @@ -1207,15 +1232,12 @@ class FirebaseFirestoreHostApi { } } - Future writeBatchCommit( - FirestorePigeonFirebaseApp arg_app, - List arg_writes, - ) async { + Future writeBatchCommit(FirestorePigeonFirebaseApp arg_app, + List arg_writes) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_app, arg_writes]) as List?; if (replyList == null) { @@ -1235,19 +1257,17 @@ class FirebaseFirestoreHostApi { } Future querySnapshot( - FirestorePigeonFirebaseApp arg_app, - String arg_path, - bool arg_isCollectionGroup, - PigeonQueryParameters arg_parameters, - PigeonGetOptions arg_options, - bool arg_includeMetadataChanges, - ListenSource arg_source, - ) async { + FirestorePigeonFirebaseApp arg_app, + String arg_path, + bool arg_isCollectionGroup, + PigeonQueryParameters arg_parameters, + PigeonGetOptions arg_options, + bool arg_includeMetadataChanges, + ListenSource arg_source) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([ arg_app, arg_path, @@ -1255,7 +1275,7 @@ class FirebaseFirestoreHostApi { arg_parameters, arg_options, arg_includeMetadataChanges, - arg_source.index, + arg_source.index ]) as List?; if (replyList == null) { throw PlatformException( @@ -1279,21 +1299,19 @@ class FirebaseFirestoreHostApi { } Future documentReferenceSnapshot( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_parameters, - bool arg_includeMetadataChanges, - ListenSource arg_source, - ) async { + FirestorePigeonFirebaseApp arg_app, + DocumentReferenceRequest arg_parameters, + bool arg_includeMetadataChanges, + ListenSource arg_source) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([ arg_app, arg_parameters, arg_includeMetadataChanges, - arg_source.index, + arg_source.index ]) as List?; if (replyList == null) { throw PlatformException( @@ -1317,14 +1335,12 @@ class FirebaseFirestoreHostApi { } Future persistenceCacheIndexManagerRequest( - FirestorePigeonFirebaseApp arg_app, - PersistenceCacheIndexManagerRequest arg_request, - ) async { + FirestorePigeonFirebaseApp arg_app, + PersistenceCacheIndexManagerRequest arg_request) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest', - codec, - binaryMessenger: _binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest', + codec, + binaryMessenger: _binaryMessenger); final List? replyList = await channel .send([arg_app, arg_request.index]) as List?; if (replyList == null) { @@ -1342,4 +1358,35 @@ class FirebaseFirestoreHostApi { return; } } + + Future executePipeline( + FirestorePigeonFirebaseApp arg_app, + List?> arg_stages, + Map? arg_options) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_stages, arg_options]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonPipelineSnapshot?)!; + } + } } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart index 19a5ddfdc4ee..33b146653a45 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart @@ -118,6 +118,28 @@ class PigeonQuerySnapshot { final PigeonSnapshotMetadata metadata; } +class PigeonPipelineResult { + const PigeonPipelineResult({ + required this.documentPath, + required this.createTime, + required this.updateTime, + }); + + final String documentPath; + final int createTime; // Timestamp in milliseconds since epoch + final int updateTime; // Timestamp in milliseconds since epoch +} + +class PigeonPipelineSnapshot { + const PigeonPipelineSnapshot({ + required this.results, + required this.executionTime, + }); + + final List results; + final int executionTime; // Timestamp in milliseconds since epoch +} + /// An enumeration of firestore source types. enum Source { /// Causes Firestore to try to retrieve an up-to-date (server-retrieved) snapshot, but fall back to @@ -442,4 +464,11 @@ abstract class FirebaseFirestoreHostApi { FirestorePigeonFirebaseApp app, PersistenceCacheIndexManagerRequest request, ); + + @async + PigeonPipelineSnapshot executePipeline( + FirestorePigeonFirebaseApp app, + List?> stages, + Map? options, + ); } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart index 32d57ebdcb48..67978a0a8f2c 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart @@ -6,13 +6,13 @@ // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; -import 'dart:typed_data' show Uint8List; - -import 'package:cloud_firestore_platform_interface/src/pigeon/messages.pigeon.dart'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:cloud_firestore_platform_interface/src/pigeon/messages.pigeon.dart'; + class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { const _TestFirebaseFirestoreHostApiCodec(); @override @@ -44,18 +44,24 @@ class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { } else if (value is PigeonGetOptions) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is PigeonQueryParameters) { + } else if (value is PigeonPipelineResult) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is PigeonQuerySnapshot) { + } else if (value is PigeonPipelineSnapshot) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PigeonSnapshotMetadata) { + } else if (value is PigeonQueryParameters) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PigeonTransactionCommand) { + } else if (value is PigeonQuerySnapshot) { buffer.putUint8(140); writeValue(buffer, value.encode()); + } else if (value is PigeonSnapshotMetadata) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PigeonTransactionCommand) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -63,22 +69,40 @@ class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { - return switch (type) { - 128 => AggregateQuery.decode(readValue(buffer)!), - 129 => AggregateQueryResponse.decode(readValue(buffer)!), - 130 => DocumentReferenceRequest.decode(readValue(buffer)!), - 131 => FirestorePigeonFirebaseApp.decode(readValue(buffer)!), - 132 => PigeonDocumentChange.decode(readValue(buffer)!), - 133 => PigeonDocumentOption.decode(readValue(buffer)!), - 134 => PigeonDocumentSnapshot.decode(readValue(buffer)!), - 135 => PigeonFirebaseSettings.decode(readValue(buffer)!), - 136 => PigeonGetOptions.decode(readValue(buffer)!), - 137 => PigeonQueryParameters.decode(readValue(buffer)!), - 138 => PigeonQuerySnapshot.decode(readValue(buffer)!), - 139 => PigeonSnapshotMetadata.decode(readValue(buffer)!), - 140 => PigeonTransactionCommand.decode(readValue(buffer)!), - _ => super.readValueOfType(type, buffer) - }; + switch (type) { + case 128: + return AggregateQuery.decode(readValue(buffer)!); + case 129: + return AggregateQueryResponse.decode(readValue(buffer)!); + case 130: + return DocumentReferenceRequest.decode(readValue(buffer)!); + case 131: + return FirestorePigeonFirebaseApp.decode(readValue(buffer)!); + case 132: + return PigeonDocumentChange.decode(readValue(buffer)!); + case 133: + return PigeonDocumentOption.decode(readValue(buffer)!); + case 134: + return PigeonDocumentSnapshot.decode(readValue(buffer)!); + case 135: + return PigeonFirebaseSettings.decode(readValue(buffer)!); + case 136: + return PigeonGetOptions.decode(readValue(buffer)!); + case 137: + return PigeonPipelineResult.decode(readValue(buffer)!); + case 138: + return PigeonPipelineSnapshot.decode(readValue(buffer)!); + case 139: + return PigeonQueryParameters.decode(readValue(buffer)!); + case 140: + return PigeonQuerySnapshot.decode(readValue(buffer)!); + case 141: + return PigeonSnapshotMetadata.decode(readValue(buffer)!); + case 142: + return PigeonTransactionCommand.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } } } @@ -91,10 +115,7 @@ abstract class TestFirebaseFirestoreHostApi { Future loadBundle(FirestorePigeonFirebaseApp app, Uint8List bundle); Future namedQueryGet( - FirestorePigeonFirebaseApp app, - String name, - PigeonGetOptions options, - ); + FirestorePigeonFirebaseApp app, String name, PigeonGetOptions options); Future clearPersistence(FirestorePigeonFirebaseApp app); @@ -107,106 +128,82 @@ abstract class TestFirebaseFirestoreHostApi { Future waitForPendingWrites(FirestorePigeonFirebaseApp app); Future setIndexConfiguration( - FirestorePigeonFirebaseApp app, - String indexConfiguration, - ); + FirestorePigeonFirebaseApp app, String indexConfiguration); Future setLoggingEnabled(bool loggingEnabled); Future snapshotsInSyncSetup(FirestorePigeonFirebaseApp app); Future transactionCreate( - FirestorePigeonFirebaseApp app, - int timeout, - int maxAttempts, - ); + FirestorePigeonFirebaseApp app, int timeout, int maxAttempts); Future transactionStoreResult( - String transactionId, - PigeonTransactionResult resultType, - List? commands, - ); + String transactionId, + PigeonTransactionResult resultType, + List? commands); Future transactionGet( - FirestorePigeonFirebaseApp app, - String transactionId, - String path, - ); + FirestorePigeonFirebaseApp app, String transactionId, String path); Future documentReferenceSet( - FirestorePigeonFirebaseApp app, - DocumentReferenceRequest request, - ); + FirestorePigeonFirebaseApp app, DocumentReferenceRequest request); Future documentReferenceUpdate( - FirestorePigeonFirebaseApp app, - DocumentReferenceRequest request, - ); + FirestorePigeonFirebaseApp app, DocumentReferenceRequest request); Future documentReferenceGet( - FirestorePigeonFirebaseApp app, - DocumentReferenceRequest request, - ); + FirestorePigeonFirebaseApp app, DocumentReferenceRequest request); Future documentReferenceDelete( - FirestorePigeonFirebaseApp app, - DocumentReferenceRequest request, - ); + FirestorePigeonFirebaseApp app, DocumentReferenceRequest request); Future queryGet( - FirestorePigeonFirebaseApp app, - String path, - bool isCollectionGroup, - PigeonQueryParameters parameters, - PigeonGetOptions options, - ); + FirestorePigeonFirebaseApp app, + String path, + bool isCollectionGroup, + PigeonQueryParameters parameters, + PigeonGetOptions options); Future> aggregateQuery( - FirestorePigeonFirebaseApp app, - String path, - PigeonQueryParameters parameters, - AggregateSource source, - List queries, - bool isCollectionGroup, - ); + FirestorePigeonFirebaseApp app, + String path, + PigeonQueryParameters parameters, + AggregateSource source, + List queries, + bool isCollectionGroup); Future writeBatchCommit( - FirestorePigeonFirebaseApp app, - List writes, - ); + FirestorePigeonFirebaseApp app, List writes); Future querySnapshot( - FirestorePigeonFirebaseApp app, - String path, - bool isCollectionGroup, - PigeonQueryParameters parameters, - PigeonGetOptions options, - bool includeMetadataChanges, - ListenSource source, - ); + FirestorePigeonFirebaseApp app, + String path, + bool isCollectionGroup, + PigeonQueryParameters parameters, + PigeonGetOptions options, + bool includeMetadataChanges, + ListenSource source); Future documentReferenceSnapshot( - FirestorePigeonFirebaseApp app, - DocumentReferenceRequest parameters, - bool includeMetadataChanges, - ListenSource source, - ); + FirestorePigeonFirebaseApp app, + DocumentReferenceRequest parameters, + bool includeMetadataChanges, + ListenSource source); Future persistenceCacheIndexManagerRequest( - FirestorePigeonFirebaseApp app, - PersistenceCacheIndexManagerRequest request, - ); + FirestorePigeonFirebaseApp app, + PersistenceCacheIndexManagerRequest request); + + Future executePipeline(FirestorePigeonFirebaseApp app, + List?> stages, Map? options); - static void setup( - TestFirebaseFirestoreHostApi? api, { - BinaryMessenger? binaryMessenger, - }) { + static void setup(TestFirebaseFirestoreHostApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -214,22 +211,16 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null, expected non-null FirestorePigeonFirebaseApp.'); final Uint8List? arg_bundle = (args[1] as Uint8List?); - assert( - arg_bundle != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null, expected non-null Uint8List.', - ); + assert(arg_bundle != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null, expected non-null Uint8List.'); final String output = await api.loadBundle(arg_app!, arg_bundle!); return [output]; }); @@ -237,10 +228,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -248,27 +238,19 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null FirestorePigeonFirebaseApp.'); final String? arg_name = (args[1] as String?); - assert( - arg_name != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null String.', - ); + assert(arg_name != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null String.'); final PigeonGetOptions? arg_options = (args[2] as PigeonGetOptions?); - assert( - arg_options != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null PigeonGetOptions.', - ); + assert(arg_options != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null PigeonGetOptions.'); final PigeonQuerySnapshot output = await api.namedQueryGet(arg_app!, arg_name!, arg_options!); return [output]; @@ -277,10 +259,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -288,17 +269,13 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence was null, expected non-null FirestorePigeonFirebaseApp.'); await api.clearPersistence(arg_app!); return []; }); @@ -306,10 +283,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -317,17 +293,13 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork was null, expected non-null FirestorePigeonFirebaseApp.'); await api.disableNetwork(arg_app!); return []; }); @@ -335,10 +307,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -346,17 +317,13 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork was null, expected non-null FirestorePigeonFirebaseApp.'); await api.enableNetwork(arg_app!); return []; }); @@ -364,10 +331,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -375,17 +341,13 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate was null, expected non-null FirestorePigeonFirebaseApp.'); await api.terminate(arg_app!); return []; }); @@ -393,10 +355,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -404,17 +365,13 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites was null, expected non-null FirestorePigeonFirebaseApp.'); await api.waitForPendingWrites(arg_app!); return []; }); @@ -422,10 +379,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -433,22 +389,16 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null, expected non-null FirestorePigeonFirebaseApp.'); final String? arg_indexConfiguration = (args[1] as String?); - assert( - arg_indexConfiguration != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null, expected non-null String.', - ); + assert(arg_indexConfiguration != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null, expected non-null String.'); await api.setIndexConfiguration(arg_app!, arg_indexConfiguration!); return []; }); @@ -456,10 +406,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -467,16 +416,12 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled was null.'); final List args = (message as List?)!; final bool? arg_loggingEnabled = (args[0] as bool?); - assert( - arg_loggingEnabled != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled was null, expected non-null bool.', - ); + assert(arg_loggingEnabled != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled was null, expected non-null bool.'); await api.setLoggingEnabled(arg_loggingEnabled!); return []; }); @@ -484,10 +429,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -495,17 +439,13 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup was null, expected non-null FirestorePigeonFirebaseApp.'); final String output = await api.snapshotsInSyncSetup(arg_app!); return [output]; }); @@ -513,10 +453,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -524,42 +463,30 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null FirestorePigeonFirebaseApp.'); final int? arg_timeout = (args[1] as int?); - assert( - arg_timeout != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null int.', - ); + assert(arg_timeout != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null int.'); final int? arg_maxAttempts = (args[2] as int?); - assert( - arg_maxAttempts != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null int.', - ); + assert(arg_maxAttempts != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null int.'); final String output = await api.transactionCreate( - arg_app!, - arg_timeout!, - arg_maxAttempts!, - ); + arg_app!, arg_timeout!, arg_maxAttempts!); return [output]; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -567,40 +494,30 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null.'); final List args = (message as List?)!; final String? arg_transactionId = (args[0] as String?); - assert( - arg_transactionId != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null, expected non-null String.', - ); + assert(arg_transactionId != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null, expected non-null String.'); final PigeonTransactionResult? arg_resultType = args[1] == null ? null : PigeonTransactionResult.values[args[1]! as int]; - assert( - arg_resultType != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null, expected non-null PigeonTransactionResult.', - ); + assert(arg_resultType != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null, expected non-null PigeonTransactionResult.'); final List? arg_commands = (args[2] as List?)?.cast(); await api.transactionStoreResult( - arg_transactionId!, - arg_resultType!, - arg_commands, - ); + arg_transactionId!, arg_resultType!, arg_commands); return []; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -608,27 +525,19 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null FirestorePigeonFirebaseApp.'); final String? arg_transactionId = (args[1] as String?); - assert( - arg_transactionId != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null String.', - ); + assert(arg_transactionId != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null String.'); final String? arg_path = (args[2] as String?); - assert( - arg_path != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null String.', - ); + assert(arg_path != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null String.'); final PigeonDocumentSnapshot output = await api.transactionGet(arg_app!, arg_transactionId!, arg_path!); return [output]; @@ -637,10 +546,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -648,23 +556,17 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null, expected non-null FirestorePigeonFirebaseApp.'); final DocumentReferenceRequest? arg_request = (args[1] as DocumentReferenceRequest?); - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null, expected non-null DocumentReferenceRequest.', - ); + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null, expected non-null DocumentReferenceRequest.'); await api.documentReferenceSet(arg_app!, arg_request!); return []; }); @@ -672,10 +574,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -683,23 +584,17 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null, expected non-null FirestorePigeonFirebaseApp.'); final DocumentReferenceRequest? arg_request = (args[1] as DocumentReferenceRequest?); - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null, expected non-null DocumentReferenceRequest.', - ); + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null, expected non-null DocumentReferenceRequest.'); await api.documentReferenceUpdate(arg_app!, arg_request!); return []; }); @@ -707,10 +602,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -718,23 +612,17 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null, expected non-null FirestorePigeonFirebaseApp.'); final DocumentReferenceRequest? arg_request = (args[1] as DocumentReferenceRequest?); - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null, expected non-null DocumentReferenceRequest.', - ); + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null, expected non-null DocumentReferenceRequest.'); final PigeonDocumentSnapshot output = await api.documentReferenceGet(arg_app!, arg_request!); return [output]; @@ -743,10 +631,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -754,23 +641,17 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null, expected non-null FirestorePigeonFirebaseApp.'); final DocumentReferenceRequest? arg_request = (args[1] as DocumentReferenceRequest?); - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null, expected non-null DocumentReferenceRequest.', - ); + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null, expected non-null DocumentReferenceRequest.'); await api.documentReferenceDelete(arg_app!, arg_request!); return []; }); @@ -778,10 +659,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -789,55 +669,37 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null FirestorePigeonFirebaseApp.'); final String? arg_path = (args[1] as String?); - assert( - arg_path != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null String.', - ); + assert(arg_path != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null String.'); final bool? arg_isCollectionGroup = (args[2] as bool?); - assert( - arg_isCollectionGroup != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null bool.', - ); + assert(arg_isCollectionGroup != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null bool.'); final PigeonQueryParameters? arg_parameters = (args[3] as PigeonQueryParameters?); - assert( - arg_parameters != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null PigeonQueryParameters.', - ); + assert(arg_parameters != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null PigeonQueryParameters.'); final PigeonGetOptions? arg_options = (args[4] as PigeonGetOptions?); - assert( - arg_options != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null PigeonGetOptions.', - ); - final PigeonQuerySnapshot output = await api.queryGet( - arg_app!, - arg_path!, - arg_isCollectionGroup!, - arg_parameters!, - arg_options!, - ); + assert(arg_options != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null PigeonGetOptions.'); + final PigeonQuerySnapshot output = await api.queryGet(arg_app!, + arg_path!, arg_isCollectionGroup!, arg_parameters!, arg_options!); return [output]; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -845,63 +707,47 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null FirestorePigeonFirebaseApp.'); final String? arg_path = (args[1] as String?); - assert( - arg_path != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null String.', - ); + assert(arg_path != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null String.'); final PigeonQueryParameters? arg_parameters = (args[2] as PigeonQueryParameters?); - assert( - arg_parameters != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null PigeonQueryParameters.', - ); + assert(arg_parameters != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null PigeonQueryParameters.'); final AggregateSource? arg_source = args[3] == null ? null : AggregateSource.values[args[3]! as int]; - assert( - arg_source != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null AggregateSource.', - ); + assert(arg_source != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null AggregateSource.'); final List? arg_queries = (args[4] as List?)?.cast(); - assert( - arg_queries != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null List.', - ); + assert(arg_queries != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null List.'); final bool? arg_isCollectionGroup = (args[5] as bool?); - assert( - arg_isCollectionGroup != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null bool.', - ); + assert(arg_isCollectionGroup != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null bool.'); final List output = await api.aggregateQuery( - arg_app!, - arg_path!, - arg_parameters!, - arg_source!, - arg_queries!, - arg_isCollectionGroup!, - ); + arg_app!, + arg_path!, + arg_parameters!, + arg_source!, + arg_queries!, + arg_isCollectionGroup!); return [output]; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -909,23 +755,17 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null, expected non-null FirestorePigeonFirebaseApp.'); final List? arg_writes = (args[1] as List?)?.cast(); - assert( - arg_writes != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null, expected non-null List.', - ); + assert(arg_writes != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null, expected non-null List.'); await api.writeBatchCommit(arg_app!, arg_writes!); return []; }); @@ -933,10 +773,9 @@ abstract class TestFirebaseFirestoreHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -944,68 +783,50 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null FirestorePigeonFirebaseApp.'); final String? arg_path = (args[1] as String?); - assert( - arg_path != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null String.', - ); + assert(arg_path != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null String.'); final bool? arg_isCollectionGroup = (args[2] as bool?); - assert( - arg_isCollectionGroup != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null bool.', - ); + assert(arg_isCollectionGroup != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null bool.'); final PigeonQueryParameters? arg_parameters = (args[3] as PigeonQueryParameters?); - assert( - arg_parameters != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null PigeonQueryParameters.', - ); + assert(arg_parameters != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null PigeonQueryParameters.'); final PigeonGetOptions? arg_options = (args[4] as PigeonGetOptions?); - assert( - arg_options != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null PigeonGetOptions.', - ); + assert(arg_options != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null PigeonGetOptions.'); final bool? arg_includeMetadataChanges = (args[5] as bool?); - assert( - arg_includeMetadataChanges != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null bool.', - ); + assert(arg_includeMetadataChanges != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null bool.'); final ListenSource? arg_source = args[6] == null ? null : ListenSource.values[args[6]! as int]; - assert( - arg_source != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null ListenSource.', - ); + assert(arg_source != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null ListenSource.'); final String output = await api.querySnapshot( - arg_app!, - arg_path!, - arg_isCollectionGroup!, - arg_parameters!, - arg_options!, - arg_includeMetadataChanges!, - arg_source!, - ); + arg_app!, + arg_path!, + arg_isCollectionGroup!, + arg_parameters!, + arg_options!, + arg_includeMetadataChanges!, + arg_source!); return [output]; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -1013,50 +834,35 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null FirestorePigeonFirebaseApp.'); final DocumentReferenceRequest? arg_parameters = (args[1] as DocumentReferenceRequest?); - assert( - arg_parameters != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null DocumentReferenceRequest.', - ); + assert(arg_parameters != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null DocumentReferenceRequest.'); final bool? arg_includeMetadataChanges = (args[2] as bool?); - assert( - arg_includeMetadataChanges != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null bool.', - ); + assert(arg_includeMetadataChanges != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null bool.'); final ListenSource? arg_source = args[3] == null ? null : ListenSource.values[args[3]! as int]; - assert( - arg_source != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null ListenSource.', - ); - final String output = await api.documentReferenceSnapshot( - arg_app!, - arg_parameters!, - arg_includeMetadataChanges!, - arg_source!, - ); + assert(arg_source != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null ListenSource.'); + final String output = await api.documentReferenceSnapshot(arg_app!, + arg_parameters!, arg_includeMetadataChanges!, arg_source!); return [output]; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest', - codec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest', + codec, + binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, null); @@ -1064,29 +870,54 @@ abstract class TestFirebaseFirestoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null.'); final List args = (message as List?)!; final FirestorePigeonFirebaseApp? arg_app = (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null, expected non-null FirestorePigeonFirebaseApp.', - ); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null, expected non-null FirestorePigeonFirebaseApp.'); final PersistenceCacheIndexManagerRequest? arg_request = args[1] == null ? null : PersistenceCacheIndexManagerRequest.values[args[1]! as int]; - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null, expected non-null PersistenceCacheIndexManagerRequest.', - ); + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null, expected non-null PersistenceCacheIndexManagerRequest.'); await api.persistenceCacheIndexManagerRequest(arg_app!, arg_request!); return []; }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null.'); + final List args = (message as List?)!; + final FirestorePigeonFirebaseApp? arg_app = + (args[0] as FirestorePigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null, expected non-null FirestorePigeonFirebaseApp.'); + final List?>? arg_stages = + (args[1] as List?)?.cast?>(); + assert(arg_stages != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null, expected non-null List?>.'); + final Map? arg_options = + (args[2] as Map?)?.cast(); + final PigeonPipelineSnapshot output = + await api.executePipeline(arg_app!, arg_stages!, arg_options); + return [output]; + }); + } + } } }