@firebase/firestore 3.5.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/firestore/lite/index.d.ts +2 -0
  3. package/dist/firestore/src/api/aggregate.d.ts +43 -0
  4. package/dist/firestore/src/api/database.d.ts +15 -15
  5. package/dist/firestore/src/api.d.ts +2 -0
  6. package/dist/firestore/src/core/count_query_runner.d.ts +32 -0
  7. package/dist/firestore/src/core/firestore_client.d.ts +5 -0
  8. package/dist/firestore/src/lite-api/aggregate.d.ts +48 -0
  9. package/dist/firestore/src/lite-api/aggregate_types.d.ts +69 -0
  10. package/dist/firestore/src/lite-api/database.d.ts +7 -7
  11. package/dist/firestore/src/platform/node/grpc_connection.d.ts +1 -0
  12. package/dist/firestore/src/protos/firestore_proto_api.d.ts +28 -0
  13. package/dist/firestore/src/remote/connection.d.ts +7 -0
  14. package/dist/firestore/src/remote/datastore.d.ts +2 -0
  15. package/dist/firestore/src/remote/rest_connection.d.ts +1 -0
  16. package/dist/firestore/src/remote/serializer.d.ts +2 -1
  17. package/dist/firestore/test/integration/api/aggregation.test.d.ts +17 -0
  18. package/dist/firestore/test/integration/api_internal/aggregation.test.d.ts +17 -0
  19. package/dist/firestore/test/integration/util/helpers.d.ts +1 -0
  20. package/dist/firestore/test/unit/specs/spec_test_components.d.ts +1 -0
  21. package/dist/index.d.ts +196 -14
  22. package/dist/index.esm2017.js +4616 -4413
  23. package/dist/index.esm2017.js.map +1 -1
  24. package/dist/index.esm5.js +4608 -4402
  25. package/dist/index.esm5.js.map +1 -1
  26. package/dist/index.node.cjs.js +994 -613
  27. package/dist/index.node.cjs.js.map +1 -1
  28. package/dist/index.node.mjs +992 -615
  29. package/dist/index.node.mjs.map +1 -1
  30. package/dist/index.rn.js +4622 -4419
  31. package/dist/index.rn.js.map +1 -1
  32. package/dist/internal.d.ts +139 -17
  33. package/dist/lite/firestore/lite/index.d.ts +2 -0
  34. package/dist/lite/firestore/src/api/aggregate.d.ts +43 -0
  35. package/dist/lite/firestore/src/api/database.d.ts +15 -15
  36. package/dist/lite/firestore/src/api.d.ts +2 -0
  37. package/dist/lite/firestore/src/core/count_query_runner.d.ts +32 -0
  38. package/dist/lite/firestore/src/core/firestore_client.d.ts +5 -0
  39. package/dist/lite/firestore/src/lite-api/aggregate.d.ts +48 -0
  40. package/dist/lite/firestore/src/lite-api/aggregate_types.d.ts +69 -0
  41. package/dist/lite/firestore/src/lite-api/database.d.ts +7 -7
  42. package/dist/lite/firestore/src/platform/node/grpc_connection.d.ts +1 -0
  43. package/dist/lite/firestore/src/protos/firestore_proto_api.d.ts +28 -0
  44. package/dist/lite/firestore/src/remote/connection.d.ts +7 -0
  45. package/dist/lite/firestore/src/remote/datastore.d.ts +2 -0
  46. package/dist/lite/firestore/src/remote/rest_connection.d.ts +1 -0
  47. package/dist/lite/firestore/src/remote/serializer.d.ts +2 -1
  48. package/dist/lite/firestore/test/integration/api/aggregation.test.d.ts +17 -0
  49. package/dist/lite/firestore/test/integration/api_internal/aggregation.test.d.ts +17 -0
  50. package/dist/lite/firestore/test/integration/util/helpers.d.ts +1 -0
  51. package/dist/lite/firestore/test/unit/specs/spec_test_components.d.ts +1 -0
  52. package/dist/lite/index.browser.esm2017.js +1250 -1086
  53. package/dist/lite/index.browser.esm2017.js.map +1 -1
  54. package/dist/lite/index.browser.esm5.js +1394 -1232
  55. package/dist/lite/index.browser.esm5.js.map +1 -1
  56. package/dist/lite/index.d.ts +84 -4
  57. package/dist/lite/index.node.cjs.js +255 -63
  58. package/dist/lite/index.node.cjs.js.map +1 -1
  59. package/dist/lite/index.node.mjs +253 -65
  60. package/dist/lite/index.node.mjs.map +1 -1
  61. package/dist/lite/index.rn.esm2017.js +1257 -1093
  62. package/dist/lite/index.rn.esm2017.js.map +1 -1
  63. package/dist/lite/internal.d.ts +121 -6
  64. package/dist/lite/packages/firestore/dist/lite/index.browser.esm2017.d.ts +227 -142
  65. package/dist/lite/packages/firestore/lite/index.d.ts +2 -0
  66. package/dist/lite/packages/firestore/src/api/aggregate.d.ts +43 -0
  67. package/dist/lite/packages/firestore/src/api/database.d.ts +15 -15
  68. package/dist/lite/packages/firestore/src/api.d.ts +2 -0
  69. package/dist/lite/packages/firestore/src/core/count_query_runner.d.ts +32 -0
  70. package/dist/lite/packages/firestore/src/core/firestore_client.d.ts +5 -0
  71. package/dist/lite/packages/firestore/src/lite-api/aggregate.d.ts +48 -0
  72. package/dist/lite/packages/firestore/src/lite-api/aggregate_types.d.ts +69 -0
  73. package/dist/lite/packages/firestore/src/lite-api/database.d.ts +7 -7
  74. package/dist/lite/packages/firestore/src/platform/node/grpc_connection.d.ts +1 -0
  75. package/dist/lite/packages/firestore/src/protos/firestore_proto_api.d.ts +28 -0
  76. package/dist/lite/packages/firestore/src/remote/connection.d.ts +7 -0
  77. package/dist/lite/packages/firestore/src/remote/datastore.d.ts +2 -0
  78. package/dist/lite/packages/firestore/src/remote/rest_connection.d.ts +1 -0
  79. package/dist/lite/packages/firestore/src/remote/serializer.d.ts +2 -1
  80. package/dist/lite/packages/firestore/test/integration/api/aggregation.test.d.ts +17 -0
  81. package/dist/lite/packages/firestore/test/integration/api_internal/aggregation.test.d.ts +17 -0
  82. package/dist/lite/packages/firestore/test/integration/util/helpers.d.ts +1 -0
  83. package/dist/lite/packages/firestore/test/unit/specs/spec_test_components.d.ts +1 -0
  84. package/dist/lite/private.d.ts +119 -4
  85. package/dist/packages/firestore/dist/index.esm2017.d.ts +336 -254
  86. package/dist/packages/firestore/lite/index.d.ts +2 -0
  87. package/dist/packages/firestore/src/api/aggregate.d.ts +43 -0
  88. package/dist/packages/firestore/src/api/database.d.ts +15 -15
  89. package/dist/packages/firestore/src/api.d.ts +2 -0
  90. package/dist/packages/firestore/src/core/count_query_runner.d.ts +32 -0
  91. package/dist/packages/firestore/src/core/firestore_client.d.ts +5 -0
  92. package/dist/packages/firestore/src/lite-api/aggregate.d.ts +48 -0
  93. package/dist/packages/firestore/src/lite-api/aggregate_types.d.ts +69 -0
  94. package/dist/packages/firestore/src/lite-api/database.d.ts +7 -7
  95. package/dist/packages/firestore/src/platform/node/grpc_connection.d.ts +1 -0
  96. package/dist/packages/firestore/src/protos/firestore_proto_api.d.ts +28 -0
  97. package/dist/packages/firestore/src/remote/connection.d.ts +7 -0
  98. package/dist/packages/firestore/src/remote/datastore.d.ts +2 -0
  99. package/dist/packages/firestore/src/remote/rest_connection.d.ts +1 -0
  100. package/dist/packages/firestore/src/remote/serializer.d.ts +2 -1
  101. package/dist/packages/firestore/test/integration/api/aggregation.test.d.ts +17 -0
  102. package/dist/packages/firestore/test/integration/api_internal/aggregation.test.d.ts +17 -0
  103. package/dist/packages/firestore/test/integration/util/helpers.d.ts +1 -0
  104. package/dist/packages/firestore/test/unit/specs/spec_test_components.d.ts +1 -0
  105. package/dist/private.d.ts +234 -19
  106. package/package.json +6 -6
@@ -33,7 +33,7 @@ var grpc__namespace = /*#__PURE__*/_interopNamespace(grpc);
33
33
  var protoLoader__namespace = /*#__PURE__*/_interopNamespace(protoLoader);
34
34
 
35
35
  const name = "@firebase/firestore";
36
- const version$1 = "3.5.0";
36
+ const version$1 = "3.6.0";
37
37
 
38
38
  /**
39
39
  * @license
@@ -86,7 +86,7 @@ User.GOOGLE_CREDENTIALS = new User('google-credentials-uid');
86
86
  User.FIRST_PARTY = new User('first-party-uid');
87
87
  User.MOCK_USER = new User('mock-user');
88
88
 
89
- const version = "9.10.0";
89
+ const version = "9.11.0";
90
90
 
91
91
  /**
92
92
  * @license
@@ -8751,6 +8751,21 @@ function toQueryTarget(serializer, target) {
8751
8751
  }
8752
8752
  return result;
8753
8753
  }
8754
+ function toRunAggregationQueryRequest(serializer, target) {
8755
+ const queryTarget = toQueryTarget(serializer, target);
8756
+ return {
8757
+ structuredAggregationQuery: {
8758
+ aggregations: [
8759
+ {
8760
+ count: {},
8761
+ alias: 'count_alias'
8762
+ }
8763
+ ],
8764
+ structuredQuery: queryTarget.structuredQuery
8765
+ },
8766
+ parent: queryTarget.parent
8767
+ };
8768
+ }
8754
8769
  function convertQueryTargetToQuery(target) {
8755
8770
  let path = fromQueryPath(target.parent);
8756
8771
  const query = target.structuredQuery;
@@ -16137,7 +16152,8 @@ function localStoreGetNewDocumentChanges(localStore, collectionGroup) {
16137
16152
  /** Sets the collection group's maximum read time from the given documents. */
16138
16153
  // PORTING NOTE: Multi-Tab only.
16139
16154
  function setMaxReadTime(localStoreImpl, collectionGroup, changedDocs) {
16140
- let readTime = SnapshotVersion.min();
16155
+ let readTime = localStoreImpl.collectionGroupReadTime.get(collectionGroup) ||
16156
+ SnapshotVersion.min();
16141
16157
  changedDocs.forEach((_, doc) => {
16142
16158
  if (doc.readTime.compareTo(readTime) > 0) {
16143
16159
  readTime = doc.readTime;
@@ -17429,6 +17445,11 @@ class GrpcConnection {
17429
17445
  this.firestore = protos['google']['firestore']['v1'];
17430
17446
  this.databasePath = `projects/${databaseInfo.databaseId.projectId}/databases/${databaseInfo.databaseId.database}`;
17431
17447
  }
17448
+ get shouldResourcePathBeIncludedInRequest() {
17449
+ // Both `invokeRPC()` and `invokeStreamingRPC()` ignore their `path` arguments, and expect
17450
+ // the "path" to be part of the given `request`.
17451
+ return true;
17452
+ }
17432
17453
  ensureActiveStub() {
17433
17454
  if (!this.cachedStub) {
17434
17455
  logDebug(LOG_TAG$9, 'Creating Firestore stub.');
@@ -18475,6 +18496,15 @@ const nested = {
18475
18496
  ruby_package: "Google::Cloud::Firestore::V1"
18476
18497
  },
18477
18498
  nested: {
18499
+ AggregationResult: {
18500
+ fields: {
18501
+ aggregateFields: {
18502
+ keyType: "string",
18503
+ type: "Value",
18504
+ id: 2
18505
+ }
18506
+ }
18507
+ },
18478
18508
  DocumentMask: {
18479
18509
  fields: {
18480
18510
  fieldPaths: {
@@ -18825,6 +18855,29 @@ const nested = {
18825
18855
  }
18826
18856
  ]
18827
18857
  },
18858
+ RunAggregationQuery: {
18859
+ requestType: "RunAggregationQueryRequest",
18860
+ responseType: "RunAggregationQueryResponse",
18861
+ responseStream: true,
18862
+ options: {
18863
+ "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:runAggregationQuery",
18864
+ "(google.api.http).body": "*",
18865
+ "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runAggregationQuery",
18866
+ "(google.api.http).additional_bindings.body": "*"
18867
+ },
18868
+ parsedOptions: [
18869
+ {
18870
+ "(google.api.http)": {
18871
+ post: "/v1/{parent=projects/*/databases/*/documents}:runAggregationQuery",
18872
+ body: "*",
18873
+ additional_bindings: {
18874
+ post: "/v1/{parent=projects/*/databases/*/documents/*/**}:runAggregationQuery",
18875
+ body: "*"
18876
+ }
18877
+ }
18878
+ }
18879
+ ]
18880
+ },
18828
18881
  PartitionQuery: {
18829
18882
  requestType: "PartitionQueryRequest",
18830
18883
  responseType: "PartitionQueryResponse",
@@ -19316,6 +19369,63 @@ const nested = {
19316
19369
  }
19317
19370
  }
19318
19371
  },
19372
+ RunAggregationQueryRequest: {
19373
+ oneofs: {
19374
+ queryType: {
19375
+ oneof: [
19376
+ "structuredAggregationQuery"
19377
+ ]
19378
+ },
19379
+ consistencySelector: {
19380
+ oneof: [
19381
+ "transaction",
19382
+ "newTransaction",
19383
+ "readTime"
19384
+ ]
19385
+ }
19386
+ },
19387
+ fields: {
19388
+ parent: {
19389
+ type: "string",
19390
+ id: 1,
19391
+ options: {
19392
+ "(google.api.field_behavior)": "REQUIRED"
19393
+ }
19394
+ },
19395
+ structuredAggregationQuery: {
19396
+ type: "StructuredAggregationQuery",
19397
+ id: 2
19398
+ },
19399
+ transaction: {
19400
+ type: "bytes",
19401
+ id: 4
19402
+ },
19403
+ newTransaction: {
19404
+ type: "TransactionOptions",
19405
+ id: 5
19406
+ },
19407
+ readTime: {
19408
+ type: "google.protobuf.Timestamp",
19409
+ id: 6
19410
+ }
19411
+ }
19412
+ },
19413
+ RunAggregationQueryResponse: {
19414
+ fields: {
19415
+ result: {
19416
+ type: "AggregationResult",
19417
+ id: 1
19418
+ },
19419
+ transaction: {
19420
+ type: "bytes",
19421
+ id: 2
19422
+ },
19423
+ readTime: {
19424
+ type: "google.protobuf.Timestamp",
19425
+ id: 3
19426
+ }
19427
+ }
19428
+ },
19319
19429
  PartitionQueryRequest: {
19320
19430
  oneofs: {
19321
19431
  queryType: {
@@ -19852,6 +19962,57 @@ const nested = {
19852
19962
  }
19853
19963
  }
19854
19964
  },
19965
+ StructuredAggregationQuery: {
19966
+ oneofs: {
19967
+ queryType: {
19968
+ oneof: [
19969
+ "structuredQuery"
19970
+ ]
19971
+ }
19972
+ },
19973
+ fields: {
19974
+ structuredQuery: {
19975
+ type: "StructuredQuery",
19976
+ id: 1
19977
+ },
19978
+ aggregations: {
19979
+ rule: "repeated",
19980
+ type: "Aggregation",
19981
+ id: 3
19982
+ }
19983
+ },
19984
+ nested: {
19985
+ Aggregation: {
19986
+ oneofs: {
19987
+ operator: {
19988
+ oneof: [
19989
+ "count"
19990
+ ]
19991
+ }
19992
+ },
19993
+ fields: {
19994
+ count: {
19995
+ type: "Count",
19996
+ id: 1
19997
+ },
19998
+ alias: {
19999
+ type: "string",
20000
+ id: 7
20001
+ }
20002
+ },
20003
+ nested: {
20004
+ Count: {
20005
+ fields: {
20006
+ upTo: {
20007
+ type: "google.protobuf.Int64Value",
20008
+ id: 1
20009
+ }
20010
+ }
20011
+ }
20012
+ }
20013
+ }
20014
+ }
20015
+ },
19855
20016
  Cursor: {
19856
20017
  fields: {
19857
20018
  values: {
@@ -21092,6 +21253,19 @@ async function invokeBatchGetDocumentsRpc(datastore, keys) {
21092
21253
  });
21093
21254
  return result;
21094
21255
  }
21256
+ async function invokeRunAggregationQueryRpc(datastore, query) {
21257
+ const datastoreImpl = debugCast(datastore);
21258
+ const request = toRunAggregationQueryRequest(datastoreImpl.serializer, queryToTarget(query));
21259
+ const parent = request.parent;
21260
+ if (!datastoreImpl.connection.shouldResourcePathBeIncludedInRequest) {
21261
+ delete request.parent;
21262
+ }
21263
+ const response = await datastoreImpl.invokeStreamingRPC('RunAggregationQuery', parent, request, /*expectedResponseCount=*/ 1);
21264
+ return (response
21265
+ // Omit RunAggregationQueryResponse that only contain readTimes.
21266
+ .filter(proto => !!proto.result)
21267
+ .map(proto => proto.result.aggregateFields));
21268
+ }
21095
21269
  function newPersistentWriteStream(datastore, queue, listener) {
21096
21270
  const datastoreImpl = debugCast(datastore);
21097
21271
  datastoreImpl.verifyInitialized();
@@ -23649,10 +23823,15 @@ async function syncEngineEmitNewSnapsAndNotifyLocalStore(syncEngine, changes, re
23649
23823
  queriesProcessed.push(syncEngineImpl
23650
23824
  .applyDocChanges(queryView, changes, remoteEvent)
23651
23825
  .then(viewSnapshot => {
23652
- if (viewSnapshot) {
23826
+ // If there are changes, or we are handling a global snapshot, notify
23827
+ // secondary clients to update query state.
23828
+ if (viewSnapshot || remoteEvent) {
23653
23829
  if (syncEngineImpl.isPrimaryClient) {
23654
- syncEngineImpl.sharedClientState.updateQueryState(queryView.targetId, viewSnapshot.fromCache ? 'not-current' : 'current');
23830
+ syncEngineImpl.sharedClientState.updateQueryState(queryView.targetId, (viewSnapshot === null || viewSnapshot === void 0 ? void 0 : viewSnapshot.fromCache) ? 'not-current' : 'current');
23655
23831
  }
23832
+ }
23833
+ // Update views if there are actual changes.
23834
+ if (!!viewSnapshot) {
23656
23835
  newSnaps.push(viewSnapshot);
23657
23836
  const docChanges = LocalViewChanges.fromSnapshot(queryView.targetId, viewSnapshot);
23658
23837
  docChangesInAllViews.push(docChanges);
@@ -24698,6 +24877,100 @@ function newBundleReader(reader, serializer) {
24698
24877
  return new BundleReaderImpl(reader, serializer);
24699
24878
  }
24700
24879
 
24880
+ /**
24881
+ * @license
24882
+ * Copyright 2022 Google LLC
24883
+ *
24884
+ * Licensed under the Apache License, Version 2.0 (the "License");
24885
+ * you may not use this file except in compliance with the License.
24886
+ * You may obtain a copy of the License at
24887
+ *
24888
+ * http://www.apache.org/licenses/LICENSE-2.0
24889
+ *
24890
+ * Unless required by applicable law or agreed to in writing, software
24891
+ * distributed under the License is distributed on an "AS IS" BASIS,
24892
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24893
+ * See the License for the specific language governing permissions and
24894
+ * limitations under the License.
24895
+ */
24896
+ /**
24897
+ * Represents an aggregation that can be performed by Firestore.
24898
+ */
24899
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
24900
+ class AggregateField {
24901
+ constructor() {
24902
+ /** A type string to uniquely identify instances of this class. */
24903
+ this.type = 'AggregateField';
24904
+ }
24905
+ }
24906
+ /**
24907
+ * The results of executing an aggregation query.
24908
+ */
24909
+ class AggregateQuerySnapshot {
24910
+ /** @hideconstructor */
24911
+ constructor(query, _data) {
24912
+ this._data = _data;
24913
+ /** A type string to uniquely identify instances of this class. */
24914
+ this.type = 'AggregateQuerySnapshot';
24915
+ this.query = query;
24916
+ }
24917
+ /**
24918
+ * Returns the results of the aggregations performed over the underlying
24919
+ * query.
24920
+ *
24921
+ * The keys of the returned object will be the same as those of the
24922
+ * `AggregateSpec` object specified to the aggregation method, and the values
24923
+ * will be the corresponding aggregation result.
24924
+ *
24925
+ * @returns The results of the aggregations performed over the underlying
24926
+ * query.
24927
+ */
24928
+ data() {
24929
+ return this._data;
24930
+ }
24931
+ }
24932
+
24933
+ /**
24934
+ * @license
24935
+ * Copyright 2022 Google LLC
24936
+ *
24937
+ * Licensed under the Apache License, Version 2.0 (the "License");
24938
+ * you may not use this file except in compliance with the License.
24939
+ * You may obtain a copy of the License at
24940
+ *
24941
+ * http://www.apache.org/licenses/LICENSE-2.0
24942
+ *
24943
+ * Unless required by applicable law or agreed to in writing, software
24944
+ * distributed under the License is distributed on an "AS IS" BASIS,
24945
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24946
+ * See the License for the specific language governing permissions and
24947
+ * limitations under the License.
24948
+ */
24949
+ /**
24950
+ * CountQueryRunner encapsulates the logic needed to run the count aggregation
24951
+ * queries.
24952
+ */
24953
+ class CountQueryRunner {
24954
+ constructor(query, datastore, userDataWriter) {
24955
+ this.query = query;
24956
+ this.datastore = datastore;
24957
+ this.userDataWriter = userDataWriter;
24958
+ }
24959
+ run() {
24960
+ return invokeRunAggregationQueryRpc(this.datastore, this.query._query).then(result => {
24961
+ hardAssert(result[0] !== undefined);
24962
+ const counts = Object.entries(result[0])
24963
+ .filter(([key, value]) => key === 'count_alias')
24964
+ .map(([key, value]) => this.userDataWriter.convertValue(value));
24965
+ const countValue = counts[0];
24966
+ hardAssert(typeof countValue === 'number');
24967
+ return Promise.resolve(new AggregateQuerySnapshot(this.query, {
24968
+ count: countValue
24969
+ }));
24970
+ });
24971
+ }
24972
+ }
24973
+
24701
24974
  /**
24702
24975
  * @license
24703
24976
  * Copyright 2017 Google LLC
@@ -25254,6 +25527,26 @@ function firestoreClientTransaction(client, updateFunction, options) {
25254
25527
  });
25255
25528
  return deferred.promise;
25256
25529
  }
25530
+ function firestoreClientRunCountQuery(client, query, userDataWriter) {
25531
+ const deferred = new Deferred();
25532
+ client.asyncQueue.enqueueAndForget(async () => {
25533
+ try {
25534
+ const remoteStore = await getRemoteStore(client);
25535
+ if (!canUseNetwork(remoteStore)) {
25536
+ deferred.reject(new FirestoreError(Code.UNAVAILABLE, 'Failed to get count result because the client is offline.'));
25537
+ }
25538
+ else {
25539
+ const datastore = await getDatastore(client);
25540
+ const result = new CountQueryRunner(query, datastore, userDataWriter).run();
25541
+ deferred.resolve(result);
25542
+ }
25543
+ }
25544
+ catch (e) {
25545
+ deferred.reject(e);
25546
+ }
25547
+ });
25548
+ return deferred.promise;
25549
+ }
25257
25550
  async function readDocumentFromCache(localStore, docKey, result) {
25258
25551
  try {
25259
25552
  const document = await localStoreReadDocument(localStore, docKey);
@@ -25509,7 +25802,7 @@ class FirestoreSettingsImpl {
25509
25802
  /**
25510
25803
  * The Cloud Firestore service interface.
25511
25804
  *
25512
- * Do not call this constructor directly. Instead, use {@link getFirestore}.
25805
+ * Do not call this constructor directly. Instead, use {@link (getFirestore:1)}.
25513
25806
  */
25514
25807
  class Firestore$1 {
25515
25808
  /** @hideconstructor */
@@ -26251,7 +26544,7 @@ const CACHE_SIZE_UNLIMITED = LRU_COLLECTION_DISABLED;
26251
26544
  /**
26252
26545
  * The Cloud Firestore service interface.
26253
26546
  *
26254
- * Do not call this constructor directly. Instead, use {@link getFirestore}.
26547
+ * Do not call this constructor directly. Instead, use {@link (getFirestore:1)}.
26255
26548
  */
26256
26549
  class Firestore extends Firestore$1 {
26257
26550
  /** @hideconstructor */
@@ -26276,8 +26569,8 @@ class Firestore extends Firestore$1 {
26276
26569
  /**
26277
26570
  * Initializes a new instance of {@link Firestore} with the provided settings.
26278
26571
  * Can only be called before any other function, including
26279
- * {@link getFirestore}. If the custom settings are empty, this function is
26280
- * equivalent to calling {@link getFirestore}.
26572
+ * {@link (getFirestore:1)}. If the custom settings are empty, this function is
26573
+ * equivalent to calling {@link (getFirestore:1)}.
26281
26574
  *
26282
26575
  * @param app - The {@link @firebase/app#FirebaseApp} with which the {@link Firestore} instance will
26283
26576
  * be associated.
@@ -26320,9 +26613,17 @@ function getFirestore(appOrDatabaseId, optionalDatabaseId) {
26320
26613
  const databaseId = typeof appOrDatabaseId === 'string'
26321
26614
  ? appOrDatabaseId
26322
26615
  : optionalDatabaseId || DEFAULT_DATABASE_NAME;
26323
- return app._getProvider(app$1, 'firestore').getImmediate({
26616
+ const db = app._getProvider(app$1, 'firestore').getImmediate({
26324
26617
  identifier: databaseId
26325
26618
  });
26619
+ if (!db._initialized) {
26620
+ const firestoreEmulatorHost = util$1.getDefaultEmulatorHost('firestore');
26621
+ if (firestoreEmulatorHost) {
26622
+ const [host, port] = firestoreEmulatorHost.split(':');
26623
+ connectFirestoreEmulator(db, host, parseInt(port, 10));
26624
+ }
26625
+ }
26626
+ return db;
26326
26627
  }
26327
26628
  /**
26328
26629
  * @internal
@@ -26344,7 +26645,7 @@ function configureFirestore(firestore) {
26344
26645
  * Attempts to enable persistent storage, if possible.
26345
26646
  *
26346
26647
  * Must be called before any other functions (other than
26347
- * {@link initializeFirestore}, {@link getFirestore} or
26648
+ * {@link initializeFirestore}, {@link (getFirestore:1)} or
26348
26649
  * {@link clearIndexedDbPersistence}.
26349
26650
  *
26350
26651
  * If this fails, `enableIndexedDbPersistence()` will reject the promise it
@@ -26468,7 +26769,7 @@ function canFallbackFromIndexedDbError(error) {
26468
26769
  * Must be called while the {@link Firestore} instance is not started (after the app is
26469
26770
  * terminated or when the app is first initialized). On startup, this function
26470
26771
  * must be called before other functions (other than {@link
26471
- * initializeFirestore} or {@link getFirestore})). If the {@link Firestore}
26772
+ * initializeFirestore} or {@link (getFirestore:1)})). If the {@link Firestore}
26472
26773
  * instance is still running, the promise will be rejected with the error code
26473
26774
  * of `failed-precondition`.
26474
26775
  *
@@ -26552,7 +26853,7 @@ function disableNetwork(firestore) {
26552
26853
  * may be used. Any other function will throw a `FirestoreError`.
26553
26854
  *
26554
26855
  * To restart after termination, create a new instance of FirebaseFirestore with
26555
- * {@link getFirestore}.
26856
+ * {@link (getFirestore:1)}.
26556
26857
  *
26557
26858
  * Termination does not cancel any pending writes, and any promises that are
26558
26859
  * awaiting a response from the server will not be resolved. If you have
@@ -26651,7 +26952,7 @@ function registerFirestore(variant, useFetchStreams = true) {
26651
26952
 
26652
26953
  /**
26653
26954
  * @license
26654
- * Copyright 2020 Google LLC
26955
+ * Copyright 2017 Google LLC
26655
26956
  *
26656
26957
  * Licensed under the Apache License, Version 2.0 (the "License");
26657
26958
  * you may not use this file except in compliance with the License.
@@ -26665,46 +26966,24 @@ function registerFirestore(variant, useFetchStreams = true) {
26665
26966
  * See the License for the specific language governing permissions and
26666
26967
  * limitations under the License.
26667
26968
  */
26969
+ function isPartialObserver(obj) {
26970
+ return implementsAnyMethods(obj, ['next', 'error', 'complete']);
26971
+ }
26668
26972
  /**
26669
- * A `FieldPath` refers to a field in a document. The path may consist of a
26670
- * single field name (referring to a top-level field in the document), or a
26671
- * list of field names (referring to a nested field in the document).
26672
- *
26673
- * Create a `FieldPath` by providing field names. If more than one field
26674
- * name is provided, the path will point to a nested field in a document.
26973
+ * Returns true if obj is an object and contains at least one of the specified
26974
+ * methods.
26675
26975
  */
26676
- class FieldPath {
26677
- /**
26678
- * Creates a `FieldPath` from the provided field names. If more than one field
26679
- * name is provided, the path will point to a nested field in a document.
26680
- *
26681
- * @param fieldNames - A list of field names.
26682
- */
26683
- constructor(...fieldNames) {
26684
- for (let i = 0; i < fieldNames.length; ++i) {
26685
- if (fieldNames[i].length === 0) {
26686
- throw new FirestoreError(Code.INVALID_ARGUMENT, `Invalid field name at argument $(i + 1). ` +
26687
- 'Field names must not be empty.');
26688
- }
26689
- }
26690
- this._internalPath = new FieldPath$1(fieldNames);
26976
+ function implementsAnyMethods(obj, methods) {
26977
+ if (typeof obj !== 'object' || obj === null) {
26978
+ return false;
26691
26979
  }
26692
- /**
26693
- * Returns true if this `FieldPath` is equal to the provided one.
26694
- *
26695
- * @param other - The `FieldPath` to compare against.
26696
- * @returns true if this `FieldPath` is equal to the provided one.
26697
- */
26698
- isEqual(other) {
26699
- return this._internalPath.isEqual(other._internalPath);
26980
+ const object = obj;
26981
+ for (const method of methods) {
26982
+ if (method in object && typeof object[method] === 'function') {
26983
+ return true;
26984
+ }
26700
26985
  }
26701
- }
26702
- /**
26703
- * Returns a special sentinel `FieldPath` to refer to the ID of a document.
26704
- * It can be used in queries to sort or filter by the document ID.
26705
- */
26706
- function documentId() {
26707
- return new FieldPath(DOCUMENT_KEY_NAME);
26986
+ return false;
26708
26987
  }
26709
26988
 
26710
26989
  /**
@@ -26805,11 +27084,69 @@ class Bytes {
26805
27084
  * limitations under the License.
26806
27085
  */
26807
27086
  /**
26808
- * Sentinel values that can be used when writing document fields with `set()`
26809
- * or `update()`.
26810
- */
26811
- class FieldValue {
26812
- /**
27087
+ * A `FieldPath` refers to a field in a document. The path may consist of a
27088
+ * single field name (referring to a top-level field in the document), or a
27089
+ * list of field names (referring to a nested field in the document).
27090
+ *
27091
+ * Create a `FieldPath` by providing field names. If more than one field
27092
+ * name is provided, the path will point to a nested field in a document.
27093
+ */
27094
+ class FieldPath {
27095
+ /**
27096
+ * Creates a `FieldPath` from the provided field names. If more than one field
27097
+ * name is provided, the path will point to a nested field in a document.
27098
+ *
27099
+ * @param fieldNames - A list of field names.
27100
+ */
27101
+ constructor(...fieldNames) {
27102
+ for (let i = 0; i < fieldNames.length; ++i) {
27103
+ if (fieldNames[i].length === 0) {
27104
+ throw new FirestoreError(Code.INVALID_ARGUMENT, `Invalid field name at argument $(i + 1). ` +
27105
+ 'Field names must not be empty.');
27106
+ }
27107
+ }
27108
+ this._internalPath = new FieldPath$1(fieldNames);
27109
+ }
27110
+ /**
27111
+ * Returns true if this `FieldPath` is equal to the provided one.
27112
+ *
27113
+ * @param other - The `FieldPath` to compare against.
27114
+ * @returns true if this `FieldPath` is equal to the provided one.
27115
+ */
27116
+ isEqual(other) {
27117
+ return this._internalPath.isEqual(other._internalPath);
27118
+ }
27119
+ }
27120
+ /**
27121
+ * Returns a special sentinel `FieldPath` to refer to the ID of a document.
27122
+ * It can be used in queries to sort or filter by the document ID.
27123
+ */
27124
+ function documentId() {
27125
+ return new FieldPath(DOCUMENT_KEY_NAME);
27126
+ }
27127
+
27128
+ /**
27129
+ * @license
27130
+ * Copyright 2020 Google LLC
27131
+ *
27132
+ * Licensed under the Apache License, Version 2.0 (the "License");
27133
+ * you may not use this file except in compliance with the License.
27134
+ * You may obtain a copy of the License at
27135
+ *
27136
+ * http://www.apache.org/licenses/LICENSE-2.0
27137
+ *
27138
+ * Unless required by applicable law or agreed to in writing, software
27139
+ * distributed under the License is distributed on an "AS IS" BASIS,
27140
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27141
+ * See the License for the specific language governing permissions and
27142
+ * limitations under the License.
27143
+ */
27144
+ /**
27145
+ * Sentinel values that can be used when writing document fields with `set()`
27146
+ * or `update()`.
27147
+ */
27148
+ class FieldValue {
27149
+ /**
26813
27150
  * @param _methodName - The public API endpoint that returns this class.
26814
27151
  * @hideconstructor
26815
27152
  */
@@ -27710,378 +28047,87 @@ function fieldPathFromArgument(methodName, arg) {
27710
28047
  * See the License for the specific language governing permissions and
27711
28048
  * limitations under the License.
27712
28049
  */
28050
+ function validateHasExplicitOrderByForLimitToLast(query) {
28051
+ if (query.limitType === "L" /* Last */ &&
28052
+ query.explicitOrderBy.length === 0) {
28053
+ throw new FirestoreError(Code.UNIMPLEMENTED, 'limitToLast() queries require specifying at least one orderBy() clause');
28054
+ }
28055
+ }
27713
28056
  /**
27714
- * Metadata about a snapshot, describing the state of the snapshot.
28057
+ * A `QueryConstraint` is used to narrow the set of documents returned by a
28058
+ * Firestore query. `QueryConstraint`s are created by invoking {@link where},
28059
+ * {@link orderBy}, {@link (startAt:1)}, {@link (startAfter:1)}, {@link
28060
+ * endBefore:1}, {@link (endAt:1)}, {@link limit} or {@link limitToLast} and
28061
+ * can then be passed to {@link query} to create a new query instance that
28062
+ * also contains this `QueryConstraint`.
27715
28063
  */
27716
- class SnapshotMetadata {
27717
- /** @hideconstructor */
27718
- constructor(hasPendingWrites, fromCache) {
27719
- this.hasPendingWrites = hasPendingWrites;
27720
- this.fromCache = fromCache;
27721
- }
27722
- /**
27723
- * Returns true if this `SnapshotMetadata` is equal to the provided one.
27724
- *
27725
- * @param other - The `SnapshotMetadata` to compare against.
27726
- * @returns true if this `SnapshotMetadata` is equal to the provided one.
27727
- */
27728
- isEqual(other) {
27729
- return (this.hasPendingWrites === other.hasPendingWrites &&
27730
- this.fromCache === other.fromCache);
27731
- }
28064
+ class QueryConstraint {
27732
28065
  }
27733
28066
  /**
27734
- * A `DocumentSnapshot` contains data read from a document in your Firestore
27735
- * database. The data can be extracted with `.data()` or `.get(<field>)` to
27736
- * get a specific field.
28067
+ * Creates a new immutable instance of {@link Query} that is extended to also include
28068
+ * additional query constraints.
27737
28069
  *
27738
- * For a `DocumentSnapshot` that points to a non-existing document, any data
27739
- * access will return 'undefined'. You can use the `exists()` method to
27740
- * explicitly verify a document's existence.
28070
+ * @param query - The {@link Query} instance to use as a base for the new constraints.
28071
+ * @param queryConstraints - The list of {@link QueryConstraint}s to apply.
28072
+ * @throws if any of the provided query constraints cannot be combined with the
28073
+ * existing or new constraints.
27741
28074
  */
27742
- class DocumentSnapshot extends DocumentSnapshot$1 {
27743
- /** @hideconstructor protected */
27744
- constructor(_firestore, userDataWriter, key, document, metadata, converter) {
27745
- super(_firestore, userDataWriter, key, document, converter);
27746
- this._firestore = _firestore;
27747
- this._firestoreImpl = _firestore;
27748
- this.metadata = metadata;
27749
- }
27750
- /**
27751
- * Returns whether or not the data exists. True if the document exists.
27752
- */
27753
- exists() {
27754
- return super.exists();
28075
+ function query(query, ...queryConstraints) {
28076
+ for (const constraint of queryConstraints) {
28077
+ query = constraint._apply(query);
27755
28078
  }
27756
- /**
27757
- * Retrieves all fields in the document as an `Object`. Returns `undefined` if
27758
- * the document doesn't exist.
27759
- *
27760
- * By default, `serverTimestamp()` values that have not yet been
27761
- * set to their final value will be returned as `null`. You can override
27762
- * this by passing an options object.
27763
- *
27764
- * @param options - An options object to configure how data is retrieved from
27765
- * the snapshot (for example the desired behavior for server timestamps that
27766
- * have not yet been set to their final value).
27767
- * @returns An `Object` containing all fields in the document or `undefined` if
27768
- * the document doesn't exist.
27769
- */
27770
- data(options = {}) {
27771
- if (!this._document) {
27772
- return undefined;
27773
- }
27774
- else if (this._converter) {
27775
- // We only want to use the converter and create a new DocumentSnapshot
27776
- // if a converter has been provided.
27777
- const snapshot = new QueryDocumentSnapshot(this._firestore, this._userDataWriter, this._key, this._document, this.metadata,
27778
- /* converter= */ null);
27779
- return this._converter.fromFirestore(snapshot, options);
27780
- }
27781
- else {
27782
- return this._userDataWriter.convertValue(this._document.data.value, options.serverTimestamps);
27783
- }
28079
+ return query;
28080
+ }
28081
+ class QueryFilterConstraint extends QueryConstraint {
28082
+ constructor(_field, _op, _value) {
28083
+ super();
28084
+ this._field = _field;
28085
+ this._op = _op;
28086
+ this._value = _value;
28087
+ this.type = 'where';
27784
28088
  }
27785
- /**
27786
- * Retrieves the field specified by `fieldPath`. Returns `undefined` if the
27787
- * document or field doesn't exist.
27788
- *
27789
- * By default, a `serverTimestamp()` that has not yet been set to
27790
- * its final value will be returned as `null`. You can override this by
27791
- * passing an options object.
27792
- *
27793
- * @param fieldPath - The path (for example 'foo' or 'foo.bar') to a specific
27794
- * field.
27795
- * @param options - An options object to configure how the field is retrieved
27796
- * from the snapshot (for example the desired behavior for server timestamps
27797
- * that have not yet been set to their final value).
27798
- * @returns The data at the specified field location or undefined if no such
27799
- * field exists in the document.
27800
- */
27801
- // We are using `any` here to avoid an explicit cast by our users.
27802
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
27803
- get(fieldPath, options = {}) {
27804
- if (this._document) {
27805
- const value = this._document.data.field(fieldPathFromArgument('DocumentSnapshot.get', fieldPath));
27806
- if (value !== null) {
27807
- return this._userDataWriter.convertValue(value, options.serverTimestamps);
27808
- }
27809
- }
27810
- return undefined;
28089
+ _apply(query) {
28090
+ const reader = newUserDataReader(query.firestore);
28091
+ const filter = newQueryFilter(query._query, 'where', reader, query.firestore._databaseId, this._field, this._op, this._value);
28092
+ return new Query(query.firestore, query.converter, queryWithAddedFilter(query._query, filter));
27811
28093
  }
27812
28094
  }
27813
28095
  /**
27814
- * A `QueryDocumentSnapshot` contains data read from a document in your
27815
- * Firestore database as part of a query. The document is guaranteed to exist
27816
- * and its data can be extracted with `.data()` or `.get(<field>)` to get a
27817
- * specific field.
28096
+ * Creates a {@link QueryConstraint} that enforces that documents must contain the
28097
+ * specified field and that the value should satisfy the relation constraint
28098
+ * provided.
27818
28099
  *
27819
- * A `QueryDocumentSnapshot` offers the same API surface as a
27820
- * `DocumentSnapshot`. Since query results contain only existing documents, the
27821
- * `exists` property will always be true and `data()` will never return
27822
- * 'undefined'.
28100
+ * @param fieldPath - The path to compare
28101
+ * @param opStr - The operation string (e.g "&lt;", "&lt;=", "==", "&lt;",
28102
+ * "&lt;=", "!=").
28103
+ * @param value - The value for comparison
28104
+ * @returns The created {@link Query}.
27823
28105
  */
27824
- class QueryDocumentSnapshot extends DocumentSnapshot {
27825
- /**
27826
- * Retrieves all fields in the document as an `Object`.
27827
- *
27828
- * By default, `serverTimestamp()` values that have not yet been
27829
- * set to their final value will be returned as `null`. You can override
27830
- * this by passing an options object.
27831
- *
27832
- * @override
27833
- * @param options - An options object to configure how data is retrieved from
27834
- * the snapshot (for example the desired behavior for server timestamps that
27835
- * have not yet been set to their final value).
27836
- * @returns An `Object` containing all fields in the document.
27837
- */
27838
- data(options = {}) {
27839
- return super.data(options);
28106
+ function where(fieldPath, opStr, value) {
28107
+ const op = opStr;
28108
+ const field = fieldPathFromArgument('where', fieldPath);
28109
+ return new QueryFilterConstraint(field, op, value);
28110
+ }
28111
+ class QueryOrderByConstraint extends QueryConstraint {
28112
+ constructor(_field, _direction) {
28113
+ super();
28114
+ this._field = _field;
28115
+ this._direction = _direction;
28116
+ this.type = 'orderBy';
28117
+ }
28118
+ _apply(query) {
28119
+ const orderBy = newQueryOrderBy(query._query, this._field, this._direction);
28120
+ return new Query(query.firestore, query.converter, queryWithAddedOrderBy(query._query, orderBy));
27840
28121
  }
27841
28122
  }
27842
28123
  /**
27843
- * A `QuerySnapshot` contains zero or more `DocumentSnapshot` objects
27844
- * representing the results of a query. The documents can be accessed as an
27845
- * array via the `docs` property or enumerated using the `forEach` method. The
27846
- * number of documents can be determined via the `empty` and `size`
27847
- * properties.
27848
- */
27849
- class QuerySnapshot {
27850
- /** @hideconstructor */
27851
- constructor(_firestore, _userDataWriter, query, _snapshot) {
27852
- this._firestore = _firestore;
27853
- this._userDataWriter = _userDataWriter;
27854
- this._snapshot = _snapshot;
27855
- this.metadata = new SnapshotMetadata(_snapshot.hasPendingWrites, _snapshot.fromCache);
27856
- this.query = query;
27857
- }
27858
- /** An array of all the documents in the `QuerySnapshot`. */
27859
- get docs() {
27860
- const result = [];
27861
- this.forEach(doc => result.push(doc));
27862
- return result;
27863
- }
27864
- /** The number of documents in the `QuerySnapshot`. */
27865
- get size() {
27866
- return this._snapshot.docs.size;
27867
- }
27868
- /** True if there are no documents in the `QuerySnapshot`. */
27869
- get empty() {
27870
- return this.size === 0;
27871
- }
27872
- /**
27873
- * Enumerates all of the documents in the `QuerySnapshot`.
27874
- *
27875
- * @param callback - A callback to be called with a `QueryDocumentSnapshot` for
27876
- * each document in the snapshot.
27877
- * @param thisArg - The `this` binding for the callback.
27878
- */
27879
- forEach(callback, thisArg) {
27880
- this._snapshot.docs.forEach(doc => {
27881
- callback.call(thisArg, new QueryDocumentSnapshot(this._firestore, this._userDataWriter, doc.key, doc, new SnapshotMetadata(this._snapshot.mutatedKeys.has(doc.key), this._snapshot.fromCache), this.query.converter));
27882
- });
27883
- }
27884
- /**
27885
- * Returns an array of the documents changes since the last snapshot. If this
27886
- * is the first snapshot, all documents will be in the list as 'added'
27887
- * changes.
27888
- *
27889
- * @param options - `SnapshotListenOptions` that control whether metadata-only
27890
- * changes (i.e. only `DocumentSnapshot.metadata` changed) should trigger
27891
- * snapshot events.
27892
- */
27893
- docChanges(options = {}) {
27894
- const includeMetadataChanges = !!options.includeMetadataChanges;
27895
- if (includeMetadataChanges && this._snapshot.excludesMetadataChanges) {
27896
- throw new FirestoreError(Code.INVALID_ARGUMENT, 'To include metadata changes with your document changes, you must ' +
27897
- 'also pass { includeMetadataChanges:true } to onSnapshot().');
27898
- }
27899
- if (!this._cachedChanges ||
27900
- this._cachedChangesIncludeMetadataChanges !== includeMetadataChanges) {
27901
- this._cachedChanges = changesFromSnapshot(this, includeMetadataChanges);
27902
- this._cachedChangesIncludeMetadataChanges = includeMetadataChanges;
27903
- }
27904
- return this._cachedChanges;
27905
- }
27906
- }
27907
- /** Calculates the array of `DocumentChange`s for a given `ViewSnapshot`. */
27908
- function changesFromSnapshot(querySnapshot, includeMetadataChanges) {
27909
- if (querySnapshot._snapshot.oldDocs.isEmpty()) {
27910
- let index = 0;
27911
- return querySnapshot._snapshot.docChanges.map(change => {
27912
- const doc = new QueryDocumentSnapshot(querySnapshot._firestore, querySnapshot._userDataWriter, change.doc.key, change.doc, new SnapshotMetadata(querySnapshot._snapshot.mutatedKeys.has(change.doc.key), querySnapshot._snapshot.fromCache), querySnapshot.query.converter);
27913
- return {
27914
- type: 'added',
27915
- doc,
27916
- oldIndex: -1,
27917
- newIndex: index++
27918
- };
27919
- });
27920
- }
27921
- else {
27922
- // A `DocumentSet` that is updated incrementally as changes are applied to use
27923
- // to lookup the index of a document.
27924
- let indexTracker = querySnapshot._snapshot.oldDocs;
27925
- return querySnapshot._snapshot.docChanges
27926
- .filter(change => includeMetadataChanges || change.type !== 3 /* Metadata */)
27927
- .map(change => {
27928
- const doc = new QueryDocumentSnapshot(querySnapshot._firestore, querySnapshot._userDataWriter, change.doc.key, change.doc, new SnapshotMetadata(querySnapshot._snapshot.mutatedKeys.has(change.doc.key), querySnapshot._snapshot.fromCache), querySnapshot.query.converter);
27929
- let oldIndex = -1;
27930
- let newIndex = -1;
27931
- if (change.type !== 0 /* Added */) {
27932
- oldIndex = indexTracker.indexOf(change.doc.key);
27933
- indexTracker = indexTracker.delete(change.doc.key);
27934
- }
27935
- if (change.type !== 1 /* Removed */) {
27936
- indexTracker = indexTracker.add(change.doc);
27937
- newIndex = indexTracker.indexOf(change.doc.key);
27938
- }
27939
- return {
27940
- type: resultChangeType(change.type),
27941
- doc,
27942
- oldIndex,
27943
- newIndex
27944
- };
27945
- });
27946
- }
27947
- }
27948
- function resultChangeType(type) {
27949
- switch (type) {
27950
- case 0 /* Added */:
27951
- return 'added';
27952
- case 2 /* Modified */:
27953
- case 3 /* Metadata */:
27954
- return 'modified';
27955
- case 1 /* Removed */:
27956
- return 'removed';
27957
- default:
27958
- return fail();
27959
- }
27960
- }
27961
- // TODO(firestoreexp): Add tests for snapshotEqual with different snapshot
27962
- // metadata
27963
- /**
27964
- * Returns true if the provided snapshots are equal.
27965
- *
27966
- * @param left - A snapshot to compare.
27967
- * @param right - A snapshot to compare.
27968
- * @returns true if the snapshots are equal.
27969
- */
27970
- function snapshotEqual(left, right) {
27971
- if (left instanceof DocumentSnapshot && right instanceof DocumentSnapshot) {
27972
- return (left._firestore === right._firestore &&
27973
- left._key.isEqual(right._key) &&
27974
- (left._document === null
27975
- ? right._document === null
27976
- : left._document.isEqual(right._document)) &&
27977
- left._converter === right._converter);
27978
- }
27979
- else if (left instanceof QuerySnapshot && right instanceof QuerySnapshot) {
27980
- return (left._firestore === right._firestore &&
27981
- queryEqual(left.query, right.query) &&
27982
- left.metadata.isEqual(right.metadata) &&
27983
- left._snapshot.isEqual(right._snapshot));
27984
- }
27985
- return false;
27986
- }
27987
-
27988
- /**
27989
- * @license
27990
- * Copyright 2020 Google LLC
27991
- *
27992
- * Licensed under the Apache License, Version 2.0 (the "License");
27993
- * you may not use this file except in compliance with the License.
27994
- * You may obtain a copy of the License at
27995
- *
27996
- * http://www.apache.org/licenses/LICENSE-2.0
27997
- *
27998
- * Unless required by applicable law or agreed to in writing, software
27999
- * distributed under the License is distributed on an "AS IS" BASIS,
28000
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28001
- * See the License for the specific language governing permissions and
28002
- * limitations under the License.
28003
- */
28004
- function validateHasExplicitOrderByForLimitToLast(query) {
28005
- if (query.limitType === "L" /* Last */ &&
28006
- query.explicitOrderBy.length === 0) {
28007
- throw new FirestoreError(Code.UNIMPLEMENTED, 'limitToLast() queries require specifying at least one orderBy() clause');
28008
- }
28009
- }
28010
- /**
28011
- * A `QueryConstraint` is used to narrow the set of documents returned by a
28012
- * Firestore query. `QueryConstraint`s are created by invoking {@link where},
28013
- * {@link orderBy}, {@link (startAt:1)}, {@link (startAfter:1)}, {@link
28014
- * endBefore:1}, {@link (endAt:1)}, {@link limit} or {@link limitToLast} and
28015
- * can then be passed to {@link query} to create a new query instance that
28016
- * also contains this `QueryConstraint`.
28017
- */
28018
- class QueryConstraint {
28019
- }
28020
- /**
28021
- * Creates a new immutable instance of {@link Query} that is extended to also include
28022
- * additional query constraints.
28023
- *
28024
- * @param query - The {@link Query} instance to use as a base for the new constraints.
28025
- * @param queryConstraints - The list of {@link QueryConstraint}s to apply.
28026
- * @throws if any of the provided query constraints cannot be combined with the
28027
- * existing or new constraints.
28028
- */
28029
- function query(query, ...queryConstraints) {
28030
- for (const constraint of queryConstraints) {
28031
- query = constraint._apply(query);
28032
- }
28033
- return query;
28034
- }
28035
- class QueryFilterConstraint extends QueryConstraint {
28036
- constructor(_field, _op, _value) {
28037
- super();
28038
- this._field = _field;
28039
- this._op = _op;
28040
- this._value = _value;
28041
- this.type = 'where';
28042
- }
28043
- _apply(query) {
28044
- const reader = newUserDataReader(query.firestore);
28045
- const filter = newQueryFilter(query._query, 'where', reader, query.firestore._databaseId, this._field, this._op, this._value);
28046
- return new Query(query.firestore, query.converter, queryWithAddedFilter(query._query, filter));
28047
- }
28048
- }
28049
- /**
28050
- * Creates a {@link QueryConstraint} that enforces that documents must contain the
28051
- * specified field and that the value should satisfy the relation constraint
28052
- * provided.
28053
- *
28054
- * @param fieldPath - The path to compare
28055
- * @param opStr - The operation string (e.g "&lt;", "&lt;=", "==", "&lt;",
28056
- * "&lt;=", "!=").
28057
- * @param value - The value for comparison
28058
- * @returns The created {@link Query}.
28059
- */
28060
- function where(fieldPath, opStr, value) {
28061
- const op = opStr;
28062
- const field = fieldPathFromArgument('where', fieldPath);
28063
- return new QueryFilterConstraint(field, op, value);
28064
- }
28065
- class QueryOrderByConstraint extends QueryConstraint {
28066
- constructor(_field, _direction) {
28067
- super();
28068
- this._field = _field;
28069
- this._direction = _direction;
28070
- this.type = 'orderBy';
28071
- }
28072
- _apply(query) {
28073
- const orderBy = newQueryOrderBy(query._query, this._field, this._direction);
28074
- return new Query(query.firestore, query.converter, queryWithAddedOrderBy(query._query, orderBy));
28075
- }
28076
- }
28077
- /**
28078
- * Creates a {@link QueryConstraint} that sorts the query result by the
28079
- * specified field, optionally in descending order instead of ascending.
28080
- *
28081
- * @param fieldPath - The field to sort by.
28082
- * @param directionStr - Optional direction to sort by ('asc' or 'desc'). If
28083
- * not specified, order will be ascending.
28084
- * @returns The created {@link Query}.
28124
+ * Creates a {@link QueryConstraint} that sorts the query result by the
28125
+ * specified field, optionally in descending order instead of ascending.
28126
+ *
28127
+ * @param fieldPath - The field to sort by.
28128
+ * @param directionStr - Optional direction to sort by ('asc' or 'desc'). If
28129
+ * not specified, order will be ascending.
28130
+ * @returns The created {@link Query}.
28085
28131
  */
28086
28132
  function orderBy(fieldPath, directionStr = 'asc') {
28087
28133
  const direction = directionStr;
@@ -28445,31 +28491,6 @@ function validateOrderByAndInequalityMatch(baseQuery, inequality, orderBy) {
28445
28491
  }
28446
28492
  }
28447
28493
 
28448
- /**
28449
- * @license
28450
- * Copyright 2022 Google LLC
28451
- *
28452
- * Licensed under the Apache License, Version 2.0 (the "License");
28453
- * you may not use this file except in compliance with the License.
28454
- * You may obtain a copy of the License at
28455
- *
28456
- * http://www.apache.org/licenses/LICENSE-2.0
28457
- *
28458
- * Unless required by applicable law or agreed to in writing, software
28459
- * distributed under the License is distributed on an "AS IS" BASIS,
28460
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28461
- * See the License for the specific language governing permissions and
28462
- * limitations under the License.
28463
- */
28464
- const DEFAULT_TRANSACTION_OPTIONS = {
28465
- maxAttempts: 5
28466
- };
28467
- function validateTransactionOptions(options) {
28468
- if (options.maxAttempts < 1) {
28469
- throw new FirestoreError(Code.INVALID_ARGUMENT, 'Max attempts must be at least 1');
28470
- }
28471
- }
28472
-
28473
28494
  /**
28474
28495
  * @license
28475
28496
  * Copyright 2020 Google LLC
@@ -28644,221 +28665,276 @@ class LiteUserDataWriter extends AbstractUserDataWriter {
28644
28665
  * limitations under the License.
28645
28666
  */
28646
28667
  /**
28647
- * A write batch, used to perform multiple writes as a single atomic unit.
28648
- *
28649
- * A `WriteBatch` object can be acquired by calling {@link writeBatch}. It
28650
- * provides methods for adding writes to the write batch. None of the writes
28651
- * will be committed (or visible locally) until {@link WriteBatch.commit} is
28652
- * called.
28668
+ * Metadata about a snapshot, describing the state of the snapshot.
28653
28669
  */
28654
- class WriteBatch {
28670
+ class SnapshotMetadata {
28655
28671
  /** @hideconstructor */
28656
- constructor(_firestore, _commitHandler) {
28657
- this._firestore = _firestore;
28658
- this._commitHandler = _commitHandler;
28659
- this._mutations = [];
28660
- this._committed = false;
28661
- this._dataReader = newUserDataReader(_firestore);
28672
+ constructor(hasPendingWrites, fromCache) {
28673
+ this.hasPendingWrites = hasPendingWrites;
28674
+ this.fromCache = fromCache;
28662
28675
  }
28663
- set(documentRef, data, options) {
28664
- this._verifyNotCommitted();
28665
- const ref = validateReference(documentRef, this._firestore);
28666
- const convertedValue = applyFirestoreDataConverter(ref.converter, data, options);
28667
- const parsed = parseSetData(this._dataReader, 'WriteBatch.set', ref._key, convertedValue, ref.converter !== null, options);
28668
- this._mutations.push(parsed.toMutation(ref._key, Precondition.none()));
28669
- return this;
28676
+ /**
28677
+ * Returns true if this `SnapshotMetadata` is equal to the provided one.
28678
+ *
28679
+ * @param other - The `SnapshotMetadata` to compare against.
28680
+ * @returns true if this `SnapshotMetadata` is equal to the provided one.
28681
+ */
28682
+ isEqual(other) {
28683
+ return (this.hasPendingWrites === other.hasPendingWrites &&
28684
+ this.fromCache === other.fromCache);
28670
28685
  }
28671
- update(documentRef, fieldOrUpdateData, value, ...moreFieldsAndValues) {
28672
- this._verifyNotCommitted();
28673
- const ref = validateReference(documentRef, this._firestore);
28674
- // For Compat types, we have to "extract" the underlying types before
28675
- // performing validation.
28676
- fieldOrUpdateData = util$1.getModularInstance(fieldOrUpdateData);
28677
- let parsed;
28678
- if (typeof fieldOrUpdateData === 'string' ||
28679
- fieldOrUpdateData instanceof FieldPath) {
28680
- parsed = parseUpdateVarargs(this._dataReader, 'WriteBatch.update', ref._key, fieldOrUpdateData, value, moreFieldsAndValues);
28681
- }
28682
- else {
28683
- parsed = parseUpdateData(this._dataReader, 'WriteBatch.update', ref._key, fieldOrUpdateData);
28684
- }
28685
- this._mutations.push(parsed.toMutation(ref._key, Precondition.exists(true)));
28686
- return this;
28686
+ }
28687
+ /**
28688
+ * A `DocumentSnapshot` contains data read from a document in your Firestore
28689
+ * database. The data can be extracted with `.data()` or `.get(<field>)` to
28690
+ * get a specific field.
28691
+ *
28692
+ * For a `DocumentSnapshot` that points to a non-existing document, any data
28693
+ * access will return 'undefined'. You can use the `exists()` method to
28694
+ * explicitly verify a document's existence.
28695
+ */
28696
+ class DocumentSnapshot extends DocumentSnapshot$1 {
28697
+ /** @hideconstructor protected */
28698
+ constructor(_firestore, userDataWriter, key, document, metadata, converter) {
28699
+ super(_firestore, userDataWriter, key, document, converter);
28700
+ this._firestore = _firestore;
28701
+ this._firestoreImpl = _firestore;
28702
+ this.metadata = metadata;
28687
28703
  }
28688
28704
  /**
28689
- * Deletes the document referred to by the provided {@link DocumentReference}.
28690
- *
28691
- * @param documentRef - A reference to the document to be deleted.
28692
- * @returns This `WriteBatch` instance. Used for chaining method calls.
28705
+ * Returns whether or not the data exists. True if the document exists.
28693
28706
  */
28694
- delete(documentRef) {
28695
- this._verifyNotCommitted();
28696
- const ref = validateReference(documentRef, this._firestore);
28697
- this._mutations = this._mutations.concat(new DeleteMutation(ref._key, Precondition.none()));
28698
- return this;
28707
+ exists() {
28708
+ return super.exists();
28699
28709
  }
28700
28710
  /**
28701
- * Commits all of the writes in this write batch as a single atomic unit.
28711
+ * Retrieves all fields in the document as an `Object`. Returns `undefined` if
28712
+ * the document doesn't exist.
28702
28713
  *
28703
- * The result of these writes will only be reflected in document reads that
28704
- * occur after the returned promise resolves. If the client is offline, the
28705
- * write fails. If you would like to see local modifications or buffer writes
28706
- * until the client is online, use the full Firestore SDK.
28714
+ * By default, `serverTimestamp()` values that have not yet been
28715
+ * set to their final value will be returned as `null`. You can override
28716
+ * this by passing an options object.
28707
28717
  *
28708
- * @returns A `Promise` resolved once all of the writes in the batch have been
28709
- * successfully written to the backend as an atomic unit (note that it won't
28710
- * resolve while you're offline).
28718
+ * @param options - An options object to configure how data is retrieved from
28719
+ * the snapshot (for example the desired behavior for server timestamps that
28720
+ * have not yet been set to their final value).
28721
+ * @returns An `Object` containing all fields in the document or `undefined` if
28722
+ * the document doesn't exist.
28711
28723
  */
28712
- commit() {
28713
- this._verifyNotCommitted();
28714
- this._committed = true;
28715
- if (this._mutations.length > 0) {
28716
- return this._commitHandler(this._mutations);
28724
+ data(options = {}) {
28725
+ if (!this._document) {
28726
+ return undefined;
28727
+ }
28728
+ else if (this._converter) {
28729
+ // We only want to use the converter and create a new DocumentSnapshot
28730
+ // if a converter has been provided.
28731
+ const snapshot = new QueryDocumentSnapshot(this._firestore, this._userDataWriter, this._key, this._document, this.metadata,
28732
+ /* converter= */ null);
28733
+ return this._converter.fromFirestore(snapshot, options);
28734
+ }
28735
+ else {
28736
+ return this._userDataWriter.convertValue(this._document.data.value, options.serverTimestamps);
28717
28737
  }
28718
- return Promise.resolve();
28719
28738
  }
28720
- _verifyNotCommitted() {
28721
- if (this._committed) {
28722
- throw new FirestoreError(Code.FAILED_PRECONDITION, 'A write batch can no longer be used after commit() ' +
28723
- 'has been called.');
28739
+ /**
28740
+ * Retrieves the field specified by `fieldPath`. Returns `undefined` if the
28741
+ * document or field doesn't exist.
28742
+ *
28743
+ * By default, a `serverTimestamp()` that has not yet been set to
28744
+ * its final value will be returned as `null`. You can override this by
28745
+ * passing an options object.
28746
+ *
28747
+ * @param fieldPath - The path (for example 'foo' or 'foo.bar') to a specific
28748
+ * field.
28749
+ * @param options - An options object to configure how the field is retrieved
28750
+ * from the snapshot (for example the desired behavior for server timestamps
28751
+ * that have not yet been set to their final value).
28752
+ * @returns The data at the specified field location or undefined if no such
28753
+ * field exists in the document.
28754
+ */
28755
+ // We are using `any` here to avoid an explicit cast by our users.
28756
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28757
+ get(fieldPath, options = {}) {
28758
+ if (this._document) {
28759
+ const value = this._document.data.field(fieldPathFromArgument('DocumentSnapshot.get', fieldPath));
28760
+ if (value !== null) {
28761
+ return this._userDataWriter.convertValue(value, options.serverTimestamps);
28762
+ }
28724
28763
  }
28764
+ return undefined;
28725
28765
  }
28726
28766
  }
28727
- function validateReference(documentRef, firestore) {
28728
- documentRef = util$1.getModularInstance(documentRef);
28729
- if (documentRef.firestore !== firestore) {
28730
- throw new FirestoreError(Code.INVALID_ARGUMENT, 'Provided document reference is from a different Firestore instance.');
28731
- }
28732
- else {
28733
- return documentRef;
28734
- }
28735
- }
28736
-
28737
28767
  /**
28738
- * @license
28739
- * Copyright 2020 Google LLC
28740
- *
28741
- * Licensed under the Apache License, Version 2.0 (the "License");
28742
- * you may not use this file except in compliance with the License.
28743
- * You may obtain a copy of the License at
28744
- *
28745
- * http://www.apache.org/licenses/LICENSE-2.0
28768
+ * A `QueryDocumentSnapshot` contains data read from a document in your
28769
+ * Firestore database as part of a query. The document is guaranteed to exist
28770
+ * and its data can be extracted with `.data()` or `.get(<field>)` to get a
28771
+ * specific field.
28746
28772
  *
28747
- * Unless required by applicable law or agreed to in writing, software
28748
- * distributed under the License is distributed on an "AS IS" BASIS,
28749
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28750
- * See the License for the specific language governing permissions and
28751
- * limitations under the License.
28773
+ * A `QueryDocumentSnapshot` offers the same API surface as a
28774
+ * `DocumentSnapshot`. Since query results contain only existing documents, the
28775
+ * `exists` property will always be true and `data()` will never return
28776
+ * 'undefined'.
28752
28777
  */
28753
- // TODO(mrschmidt) Consider using `BaseTransaction` as the base class in the
28754
- // legacy SDK.
28778
+ class QueryDocumentSnapshot extends DocumentSnapshot {
28779
+ /**
28780
+ * Retrieves all fields in the document as an `Object`.
28781
+ *
28782
+ * By default, `serverTimestamp()` values that have not yet been
28783
+ * set to their final value will be returned as `null`. You can override
28784
+ * this by passing an options object.
28785
+ *
28786
+ * @override
28787
+ * @param options - An options object to configure how data is retrieved from
28788
+ * the snapshot (for example the desired behavior for server timestamps that
28789
+ * have not yet been set to their final value).
28790
+ * @returns An `Object` containing all fields in the document.
28791
+ */
28792
+ data(options = {}) {
28793
+ return super.data(options);
28794
+ }
28795
+ }
28755
28796
  /**
28756
- * A reference to a transaction.
28757
- *
28758
- * The `Transaction` object passed to a transaction's `updateFunction` provides
28759
- * the methods to read and write data within the transaction context. See
28760
- * {@link runTransaction}.
28797
+ * A `QuerySnapshot` contains zero or more `DocumentSnapshot` objects
28798
+ * representing the results of a query. The documents can be accessed as an
28799
+ * array via the `docs` property or enumerated using the `forEach` method. The
28800
+ * number of documents can be determined via the `empty` and `size`
28801
+ * properties.
28761
28802
  */
28762
- class Transaction$1 {
28803
+ class QuerySnapshot {
28763
28804
  /** @hideconstructor */
28764
- constructor(_firestore, _transaction) {
28805
+ constructor(_firestore, _userDataWriter, query, _snapshot) {
28765
28806
  this._firestore = _firestore;
28766
- this._transaction = _transaction;
28767
- this._dataReader = newUserDataReader(_firestore);
28807
+ this._userDataWriter = _userDataWriter;
28808
+ this._snapshot = _snapshot;
28809
+ this.metadata = new SnapshotMetadata(_snapshot.hasPendingWrites, _snapshot.fromCache);
28810
+ this.query = query;
28811
+ }
28812
+ /** An array of all the documents in the `QuerySnapshot`. */
28813
+ get docs() {
28814
+ const result = [];
28815
+ this.forEach(doc => result.push(doc));
28816
+ return result;
28817
+ }
28818
+ /** The number of documents in the `QuerySnapshot`. */
28819
+ get size() {
28820
+ return this._snapshot.docs.size;
28821
+ }
28822
+ /** True if there are no documents in the `QuerySnapshot`. */
28823
+ get empty() {
28824
+ return this.size === 0;
28768
28825
  }
28769
28826
  /**
28770
- * Reads the document referenced by the provided {@link DocumentReference}.
28827
+ * Enumerates all of the documents in the `QuerySnapshot`.
28771
28828
  *
28772
- * @param documentRef - A reference to the document to be read.
28773
- * @returns A `DocumentSnapshot` with the read data.
28829
+ * @param callback - A callback to be called with a `QueryDocumentSnapshot` for
28830
+ * each document in the snapshot.
28831
+ * @param thisArg - The `this` binding for the callback.
28774
28832
  */
28775
- get(documentRef) {
28776
- const ref = validateReference(documentRef, this._firestore);
28777
- const userDataWriter = new LiteUserDataWriter(this._firestore);
28778
- return this._transaction.lookup([ref._key]).then(docs => {
28779
- if (!docs || docs.length !== 1) {
28780
- return fail();
28781
- }
28782
- const doc = docs[0];
28783
- if (doc.isFoundDocument()) {
28784
- return new DocumentSnapshot$1(this._firestore, userDataWriter, doc.key, doc, ref.converter);
28785
- }
28786
- else if (doc.isNoDocument()) {
28787
- return new DocumentSnapshot$1(this._firestore, userDataWriter, ref._key, null, ref.converter);
28788
- }
28789
- else {
28790
- throw fail();
28791
- }
28833
+ forEach(callback, thisArg) {
28834
+ this._snapshot.docs.forEach(doc => {
28835
+ callback.call(thisArg, new QueryDocumentSnapshot(this._firestore, this._userDataWriter, doc.key, doc, new SnapshotMetadata(this._snapshot.mutatedKeys.has(doc.key), this._snapshot.fromCache), this.query.converter));
28792
28836
  });
28793
28837
  }
28794
- set(documentRef, value, options) {
28795
- const ref = validateReference(documentRef, this._firestore);
28796
- const convertedValue = applyFirestoreDataConverter(ref.converter, value, options);
28797
- const parsed = parseSetData(this._dataReader, 'Transaction.set', ref._key, convertedValue, ref.converter !== null, options);
28798
- this._transaction.set(ref._key, parsed);
28799
- return this;
28800
- }
28801
- update(documentRef, fieldOrUpdateData, value, ...moreFieldsAndValues) {
28802
- const ref = validateReference(documentRef, this._firestore);
28803
- // For Compat types, we have to "extract" the underlying types before
28804
- // performing validation.
28805
- fieldOrUpdateData = util$1.getModularInstance(fieldOrUpdateData);
28806
- let parsed;
28807
- if (typeof fieldOrUpdateData === 'string' ||
28808
- fieldOrUpdateData instanceof FieldPath) {
28809
- parsed = parseUpdateVarargs(this._dataReader, 'Transaction.update', ref._key, fieldOrUpdateData, value, moreFieldsAndValues);
28810
- }
28811
- else {
28812
- parsed = parseUpdateData(this._dataReader, 'Transaction.update', ref._key, fieldOrUpdateData);
28813
- }
28814
- this._transaction.update(ref._key, parsed);
28815
- return this;
28816
- }
28817
28838
  /**
28818
- * Deletes the document referred to by the provided {@link DocumentReference}.
28839
+ * Returns an array of the documents changes since the last snapshot. If this
28840
+ * is the first snapshot, all documents will be in the list as 'added'
28841
+ * changes.
28819
28842
  *
28820
- * @param documentRef - A reference to the document to be deleted.
28821
- * @returns This `Transaction` instance. Used for chaining method calls.
28843
+ * @param options - `SnapshotListenOptions` that control whether metadata-only
28844
+ * changes (i.e. only `DocumentSnapshot.metadata` changed) should trigger
28845
+ * snapshot events.
28822
28846
  */
28823
- delete(documentRef) {
28824
- const ref = validateReference(documentRef, this._firestore);
28825
- this._transaction.delete(ref._key);
28826
- return this;
28847
+ docChanges(options = {}) {
28848
+ const includeMetadataChanges = !!options.includeMetadataChanges;
28849
+ if (includeMetadataChanges && this._snapshot.excludesMetadataChanges) {
28850
+ throw new FirestoreError(Code.INVALID_ARGUMENT, 'To include metadata changes with your document changes, you must ' +
28851
+ 'also pass { includeMetadataChanges:true } to onSnapshot().');
28852
+ }
28853
+ if (!this._cachedChanges ||
28854
+ this._cachedChangesIncludeMetadataChanges !== includeMetadataChanges) {
28855
+ this._cachedChanges = changesFromSnapshot(this, includeMetadataChanges);
28856
+ this._cachedChangesIncludeMetadataChanges = includeMetadataChanges;
28857
+ }
28858
+ return this._cachedChanges;
28859
+ }
28860
+ }
28861
+ /** Calculates the array of `DocumentChange`s for a given `ViewSnapshot`. */
28862
+ function changesFromSnapshot(querySnapshot, includeMetadataChanges) {
28863
+ if (querySnapshot._snapshot.oldDocs.isEmpty()) {
28864
+ let index = 0;
28865
+ return querySnapshot._snapshot.docChanges.map(change => {
28866
+ const doc = new QueryDocumentSnapshot(querySnapshot._firestore, querySnapshot._userDataWriter, change.doc.key, change.doc, new SnapshotMetadata(querySnapshot._snapshot.mutatedKeys.has(change.doc.key), querySnapshot._snapshot.fromCache), querySnapshot.query.converter);
28867
+ return {
28868
+ type: 'added',
28869
+ doc,
28870
+ oldIndex: -1,
28871
+ newIndex: index++
28872
+ };
28873
+ });
28874
+ }
28875
+ else {
28876
+ // A `DocumentSet` that is updated incrementally as changes are applied to use
28877
+ // to lookup the index of a document.
28878
+ let indexTracker = querySnapshot._snapshot.oldDocs;
28879
+ return querySnapshot._snapshot.docChanges
28880
+ .filter(change => includeMetadataChanges || change.type !== 3 /* Metadata */)
28881
+ .map(change => {
28882
+ const doc = new QueryDocumentSnapshot(querySnapshot._firestore, querySnapshot._userDataWriter, change.doc.key, change.doc, new SnapshotMetadata(querySnapshot._snapshot.mutatedKeys.has(change.doc.key), querySnapshot._snapshot.fromCache), querySnapshot.query.converter);
28883
+ let oldIndex = -1;
28884
+ let newIndex = -1;
28885
+ if (change.type !== 0 /* Added */) {
28886
+ oldIndex = indexTracker.indexOf(change.doc.key);
28887
+ indexTracker = indexTracker.delete(change.doc.key);
28888
+ }
28889
+ if (change.type !== 1 /* Removed */) {
28890
+ indexTracker = indexTracker.add(change.doc);
28891
+ newIndex = indexTracker.indexOf(change.doc.key);
28892
+ }
28893
+ return {
28894
+ type: resultChangeType(change.type),
28895
+ doc,
28896
+ oldIndex,
28897
+ newIndex
28898
+ };
28899
+ });
28900
+ }
28901
+ }
28902
+ function resultChangeType(type) {
28903
+ switch (type) {
28904
+ case 0 /* Added */:
28905
+ return 'added';
28906
+ case 2 /* Modified */:
28907
+ case 3 /* Metadata */:
28908
+ return 'modified';
28909
+ case 1 /* Removed */:
28910
+ return 'removed';
28911
+ default:
28912
+ return fail();
28827
28913
  }
28828
- }
28829
-
28830
- /**
28831
- * @license
28832
- * Copyright 2017 Google LLC
28833
- *
28834
- * Licensed under the Apache License, Version 2.0 (the "License");
28835
- * you may not use this file except in compliance with the License.
28836
- * You may obtain a copy of the License at
28837
- *
28838
- * http://www.apache.org/licenses/LICENSE-2.0
28839
- *
28840
- * Unless required by applicable law or agreed to in writing, software
28841
- * distributed under the License is distributed on an "AS IS" BASIS,
28842
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28843
- * See the License for the specific language governing permissions and
28844
- * limitations under the License.
28845
- */
28846
- function isPartialObserver(obj) {
28847
- return implementsAnyMethods(obj, ['next', 'error', 'complete']);
28848
28914
  }
28915
+ // TODO(firestoreexp): Add tests for snapshotEqual with different snapshot
28916
+ // metadata
28849
28917
  /**
28850
- * Returns true if obj is an object and contains at least one of the specified
28851
- * methods.
28918
+ * Returns true if the provided snapshots are equal.
28919
+ *
28920
+ * @param left - A snapshot to compare.
28921
+ * @param right - A snapshot to compare.
28922
+ * @returns true if the snapshots are equal.
28852
28923
  */
28853
- function implementsAnyMethods(obj, methods) {
28854
- if (typeof obj !== 'object' || obj === null) {
28855
- return false;
28924
+ function snapshotEqual(left, right) {
28925
+ if (left instanceof DocumentSnapshot && right instanceof DocumentSnapshot) {
28926
+ return (left._firestore === right._firestore &&
28927
+ left._key.isEqual(right._key) &&
28928
+ (left._document === null
28929
+ ? right._document === null
28930
+ : left._document.isEqual(right._document)) &&
28931
+ left._converter === right._converter);
28856
28932
  }
28857
- const object = obj;
28858
- for (const method of methods) {
28859
- if (method in object && typeof object[method] === 'function') {
28860
- return true;
28861
- }
28933
+ else if (left instanceof QuerySnapshot && right instanceof QuerySnapshot) {
28934
+ return (left._firestore === right._firestore &&
28935
+ queryEqual(left.query, right.query) &&
28936
+ left.metadata.isEqual(right.metadata) &&
28937
+ left._snapshot.isEqual(right._snapshot));
28862
28938
  }
28863
28939
  return false;
28864
28940
  }
@@ -29127,6 +29203,307 @@ function convertToDocSnapshot(firestore, ref, snapshot) {
29127
29203
  return new DocumentSnapshot(firestore, userDataWriter, ref._key, doc, new SnapshotMetadata(snapshot.hasPendingWrites, snapshot.fromCache), ref.converter);
29128
29204
  }
29129
29205
 
29206
+ /**
29207
+ * @license
29208
+ * Copyright 2022 Google LLC
29209
+ *
29210
+ * Licensed under the Apache License, Version 2.0 (the "License");
29211
+ * you may not use this file except in compliance with the License.
29212
+ * You may obtain a copy of the License at
29213
+ *
29214
+ * http://www.apache.org/licenses/LICENSE-2.0
29215
+ *
29216
+ * Unless required by applicable law or agreed to in writing, software
29217
+ * distributed under the License is distributed on an "AS IS" BASIS,
29218
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29219
+ * See the License for the specific language governing permissions and
29220
+ * limitations under the License.
29221
+ */
29222
+ /**
29223
+ * Compares two `AggregateQuerySnapshot` instances for equality.
29224
+ *
29225
+ * Two `AggregateQuerySnapshot` instances are considered "equal" if they have
29226
+ * underlying queries that compare equal, and the same data.
29227
+ *
29228
+ * @param left - The first `AggregateQuerySnapshot` to compare.
29229
+ * @param right - The second `AggregateQuerySnapshot` to compare.
29230
+ *
29231
+ * @returns `true` if the objects are "equal", as defined above, or `false`
29232
+ * otherwise.
29233
+ */
29234
+ function aggregateQuerySnapshotEqual(left, right) {
29235
+ return (queryEqual(left.query, right.query) && util$1.deepEqual(left.data(), right.data()));
29236
+ }
29237
+
29238
+ /**
29239
+ * @license
29240
+ * Copyright 2022 Google LLC
29241
+ *
29242
+ * Licensed under the Apache License, Version 2.0 (the "License");
29243
+ * you may not use this file except in compliance with the License.
29244
+ * You may obtain a copy of the License at
29245
+ *
29246
+ * http://www.apache.org/licenses/LICENSE-2.0
29247
+ *
29248
+ * Unless required by applicable law or agreed to in writing, software
29249
+ * distributed under the License is distributed on an "AS IS" BASIS,
29250
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29251
+ * See the License for the specific language governing permissions and
29252
+ * limitations under the License.
29253
+ */
29254
+ /**
29255
+ * Calculates the number of documents in the result set of the given query,
29256
+ * without actually downloading the documents.
29257
+ *
29258
+ * Using this function to count the documents is efficient because only the
29259
+ * final count, not the documents' data, is downloaded. This function can even
29260
+ * count the documents if the result set would be prohibitively large to
29261
+ * download entirely (e.g. thousands of documents).
29262
+ *
29263
+ * The result received from the server is presented, unaltered, without
29264
+ * considering any local state. That is, documents in the local cache are not
29265
+ * taken into consideration, neither are local modifications not yet
29266
+ * synchronized with the server. Previously-downloaded results, if any, are not
29267
+ * used: every request using this source necessarily involves a round trip to
29268
+ * the server.
29269
+ *
29270
+ * @param query - The query whose result set size to calculate.
29271
+ * @returns A Promise that will be resolved with the count; the count can be
29272
+ * retrieved from `snapshot.data().count`, where `snapshot` is the
29273
+ * `AggregateQuerySnapshot` to which the returned Promise resolves.
29274
+ */
29275
+ function getCountFromServer(query) {
29276
+ const firestore = cast(query.firestore, Firestore);
29277
+ const client = ensureFirestoreConfigured(firestore);
29278
+ const userDataWriter = new ExpUserDataWriter(firestore);
29279
+ return firestoreClientRunCountQuery(client, query, userDataWriter);
29280
+ }
29281
+
29282
+ /**
29283
+ * @license
29284
+ * Copyright 2022 Google LLC
29285
+ *
29286
+ * Licensed under the Apache License, Version 2.0 (the "License");
29287
+ * you may not use this file except in compliance with the License.
29288
+ * You may obtain a copy of the License at
29289
+ *
29290
+ * http://www.apache.org/licenses/LICENSE-2.0
29291
+ *
29292
+ * Unless required by applicable law or agreed to in writing, software
29293
+ * distributed under the License is distributed on an "AS IS" BASIS,
29294
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29295
+ * See the License for the specific language governing permissions and
29296
+ * limitations under the License.
29297
+ */
29298
+ const DEFAULT_TRANSACTION_OPTIONS = {
29299
+ maxAttempts: 5
29300
+ };
29301
+ function validateTransactionOptions(options) {
29302
+ if (options.maxAttempts < 1) {
29303
+ throw new FirestoreError(Code.INVALID_ARGUMENT, 'Max attempts must be at least 1');
29304
+ }
29305
+ }
29306
+
29307
+ /**
29308
+ * @license
29309
+ * Copyright 2020 Google LLC
29310
+ *
29311
+ * Licensed under the Apache License, Version 2.0 (the "License");
29312
+ * you may not use this file except in compliance with the License.
29313
+ * You may obtain a copy of the License at
29314
+ *
29315
+ * http://www.apache.org/licenses/LICENSE-2.0
29316
+ *
29317
+ * Unless required by applicable law or agreed to in writing, software
29318
+ * distributed under the License is distributed on an "AS IS" BASIS,
29319
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29320
+ * See the License for the specific language governing permissions and
29321
+ * limitations under the License.
29322
+ */
29323
+ /**
29324
+ * A write batch, used to perform multiple writes as a single atomic unit.
29325
+ *
29326
+ * A `WriteBatch` object can be acquired by calling {@link writeBatch}. It
29327
+ * provides methods for adding writes to the write batch. None of the writes
29328
+ * will be committed (or visible locally) until {@link WriteBatch.commit} is
29329
+ * called.
29330
+ */
29331
+ class WriteBatch {
29332
+ /** @hideconstructor */
29333
+ constructor(_firestore, _commitHandler) {
29334
+ this._firestore = _firestore;
29335
+ this._commitHandler = _commitHandler;
29336
+ this._mutations = [];
29337
+ this._committed = false;
29338
+ this._dataReader = newUserDataReader(_firestore);
29339
+ }
29340
+ set(documentRef, data, options) {
29341
+ this._verifyNotCommitted();
29342
+ const ref = validateReference(documentRef, this._firestore);
29343
+ const convertedValue = applyFirestoreDataConverter(ref.converter, data, options);
29344
+ const parsed = parseSetData(this._dataReader, 'WriteBatch.set', ref._key, convertedValue, ref.converter !== null, options);
29345
+ this._mutations.push(parsed.toMutation(ref._key, Precondition.none()));
29346
+ return this;
29347
+ }
29348
+ update(documentRef, fieldOrUpdateData, value, ...moreFieldsAndValues) {
29349
+ this._verifyNotCommitted();
29350
+ const ref = validateReference(documentRef, this._firestore);
29351
+ // For Compat types, we have to "extract" the underlying types before
29352
+ // performing validation.
29353
+ fieldOrUpdateData = util$1.getModularInstance(fieldOrUpdateData);
29354
+ let parsed;
29355
+ if (typeof fieldOrUpdateData === 'string' ||
29356
+ fieldOrUpdateData instanceof FieldPath) {
29357
+ parsed = parseUpdateVarargs(this._dataReader, 'WriteBatch.update', ref._key, fieldOrUpdateData, value, moreFieldsAndValues);
29358
+ }
29359
+ else {
29360
+ parsed = parseUpdateData(this._dataReader, 'WriteBatch.update', ref._key, fieldOrUpdateData);
29361
+ }
29362
+ this._mutations.push(parsed.toMutation(ref._key, Precondition.exists(true)));
29363
+ return this;
29364
+ }
29365
+ /**
29366
+ * Deletes the document referred to by the provided {@link DocumentReference}.
29367
+ *
29368
+ * @param documentRef - A reference to the document to be deleted.
29369
+ * @returns This `WriteBatch` instance. Used for chaining method calls.
29370
+ */
29371
+ delete(documentRef) {
29372
+ this._verifyNotCommitted();
29373
+ const ref = validateReference(documentRef, this._firestore);
29374
+ this._mutations = this._mutations.concat(new DeleteMutation(ref._key, Precondition.none()));
29375
+ return this;
29376
+ }
29377
+ /**
29378
+ * Commits all of the writes in this write batch as a single atomic unit.
29379
+ *
29380
+ * The result of these writes will only be reflected in document reads that
29381
+ * occur after the returned promise resolves. If the client is offline, the
29382
+ * write fails. If you would like to see local modifications or buffer writes
29383
+ * until the client is online, use the full Firestore SDK.
29384
+ *
29385
+ * @returns A `Promise` resolved once all of the writes in the batch have been
29386
+ * successfully written to the backend as an atomic unit (note that it won't
29387
+ * resolve while you're offline).
29388
+ */
29389
+ commit() {
29390
+ this._verifyNotCommitted();
29391
+ this._committed = true;
29392
+ if (this._mutations.length > 0) {
29393
+ return this._commitHandler(this._mutations);
29394
+ }
29395
+ return Promise.resolve();
29396
+ }
29397
+ _verifyNotCommitted() {
29398
+ if (this._committed) {
29399
+ throw new FirestoreError(Code.FAILED_PRECONDITION, 'A write batch can no longer be used after commit() ' +
29400
+ 'has been called.');
29401
+ }
29402
+ }
29403
+ }
29404
+ function validateReference(documentRef, firestore) {
29405
+ documentRef = util$1.getModularInstance(documentRef);
29406
+ if (documentRef.firestore !== firestore) {
29407
+ throw new FirestoreError(Code.INVALID_ARGUMENT, 'Provided document reference is from a different Firestore instance.');
29408
+ }
29409
+ else {
29410
+ return documentRef;
29411
+ }
29412
+ }
29413
+
29414
+ /**
29415
+ * @license
29416
+ * Copyright 2020 Google LLC
29417
+ *
29418
+ * Licensed under the Apache License, Version 2.0 (the "License");
29419
+ * you may not use this file except in compliance with the License.
29420
+ * You may obtain a copy of the License at
29421
+ *
29422
+ * http://www.apache.org/licenses/LICENSE-2.0
29423
+ *
29424
+ * Unless required by applicable law or agreed to in writing, software
29425
+ * distributed under the License is distributed on an "AS IS" BASIS,
29426
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29427
+ * See the License for the specific language governing permissions and
29428
+ * limitations under the License.
29429
+ */
29430
+ // TODO(mrschmidt) Consider using `BaseTransaction` as the base class in the
29431
+ // legacy SDK.
29432
+ /**
29433
+ * A reference to a transaction.
29434
+ *
29435
+ * The `Transaction` object passed to a transaction's `updateFunction` provides
29436
+ * the methods to read and write data within the transaction context. See
29437
+ * {@link runTransaction}.
29438
+ */
29439
+ class Transaction$1 {
29440
+ /** @hideconstructor */
29441
+ constructor(_firestore, _transaction) {
29442
+ this._firestore = _firestore;
29443
+ this._transaction = _transaction;
29444
+ this._dataReader = newUserDataReader(_firestore);
29445
+ }
29446
+ /**
29447
+ * Reads the document referenced by the provided {@link DocumentReference}.
29448
+ *
29449
+ * @param documentRef - A reference to the document to be read.
29450
+ * @returns A `DocumentSnapshot` with the read data.
29451
+ */
29452
+ get(documentRef) {
29453
+ const ref = validateReference(documentRef, this._firestore);
29454
+ const userDataWriter = new LiteUserDataWriter(this._firestore);
29455
+ return this._transaction.lookup([ref._key]).then(docs => {
29456
+ if (!docs || docs.length !== 1) {
29457
+ return fail();
29458
+ }
29459
+ const doc = docs[0];
29460
+ if (doc.isFoundDocument()) {
29461
+ return new DocumentSnapshot$1(this._firestore, userDataWriter, doc.key, doc, ref.converter);
29462
+ }
29463
+ else if (doc.isNoDocument()) {
29464
+ return new DocumentSnapshot$1(this._firestore, userDataWriter, ref._key, null, ref.converter);
29465
+ }
29466
+ else {
29467
+ throw fail();
29468
+ }
29469
+ });
29470
+ }
29471
+ set(documentRef, value, options) {
29472
+ const ref = validateReference(documentRef, this._firestore);
29473
+ const convertedValue = applyFirestoreDataConverter(ref.converter, value, options);
29474
+ const parsed = parseSetData(this._dataReader, 'Transaction.set', ref._key, convertedValue, ref.converter !== null, options);
29475
+ this._transaction.set(ref._key, parsed);
29476
+ return this;
29477
+ }
29478
+ update(documentRef, fieldOrUpdateData, value, ...moreFieldsAndValues) {
29479
+ const ref = validateReference(documentRef, this._firestore);
29480
+ // For Compat types, we have to "extract" the underlying types before
29481
+ // performing validation.
29482
+ fieldOrUpdateData = util$1.getModularInstance(fieldOrUpdateData);
29483
+ let parsed;
29484
+ if (typeof fieldOrUpdateData === 'string' ||
29485
+ fieldOrUpdateData instanceof FieldPath) {
29486
+ parsed = parseUpdateVarargs(this._dataReader, 'Transaction.update', ref._key, fieldOrUpdateData, value, moreFieldsAndValues);
29487
+ }
29488
+ else {
29489
+ parsed = parseUpdateData(this._dataReader, 'Transaction.update', ref._key, fieldOrUpdateData);
29490
+ }
29491
+ this._transaction.update(ref._key, parsed);
29492
+ return this;
29493
+ }
29494
+ /**
29495
+ * Deletes the document referred to by the provided {@link DocumentReference}.
29496
+ *
29497
+ * @param documentRef - A reference to the document to be deleted.
29498
+ * @returns This `Transaction` instance. Used for chaining method calls.
29499
+ */
29500
+ delete(documentRef) {
29501
+ const ref = validateReference(documentRef, this._firestore);
29502
+ this._transaction.delete(ref._key);
29503
+ return this;
29504
+ }
29505
+ }
29506
+
29130
29507
  /**
29131
29508
  * @license
29132
29509
  * Copyright 2020 Google LLC
@@ -29413,6 +29790,8 @@ function tryGetString(data, property) {
29413
29790
  registerFirestore('node');
29414
29791
 
29415
29792
  exports.AbstractUserDataWriter = AbstractUserDataWriter;
29793
+ exports.AggregateField = AggregateField;
29794
+ exports.AggregateQuerySnapshot = AggregateQuerySnapshot;
29416
29795
  exports.Bytes = Bytes;
29417
29796
  exports.CACHE_SIZE_UNLIMITED = CACHE_SIZE_UNLIMITED;
29418
29797
  exports.CollectionReference = CollectionReference;
@@ -29443,6 +29822,7 @@ exports._isBase64Available = isBase64Available;
29443
29822
  exports._logWarn = logWarn;
29444
29823
  exports._validateIsNotUsedTogether = validateIsNotUsedTogether;
29445
29824
  exports.addDoc = addDoc;
29825
+ exports.aggregateQuerySnapshotEqual = aggregateQuerySnapshotEqual;
29446
29826
  exports.arrayRemove = arrayRemove;
29447
29827
  exports.arrayUnion = arrayUnion;
29448
29828
  exports.clearIndexedDbPersistence = clearIndexedDbPersistence;
@@ -29461,6 +29841,7 @@ exports.endAt = endAt;
29461
29841
  exports.endBefore = endBefore;
29462
29842
  exports.ensureFirestoreConfigured = ensureFirestoreConfigured;
29463
29843
  exports.executeWrite = executeWrite;
29844
+ exports.getCountFromServer = getCountFromServer;
29464
29845
  exports.getDoc = getDoc;
29465
29846
  exports.getDocFromCache = getDocFromCache;
29466
29847
  exports.getDocFromServer = getDocFromServer;