@firebase/firestore 3.4.3 → 3.4.4-canary.0482aa5b7

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 (125) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/firestore/src/api/database.d.ts +14 -9
  3. package/dist/firestore/src/api/{query.d.ts → filter.d.ts} +0 -0
  4. package/dist/firestore/src/api/index_configuration.d.ts +117 -0
  5. package/dist/firestore/src/api/snapshot.d.ts +1 -2
  6. package/dist/firestore/src/api.d.ts +2 -1
  7. package/dist/firestore/src/core/database_info.d.ts +1 -0
  8. package/dist/firestore/src/core/firestore_client.d.ts +2 -0
  9. package/dist/firestore/src/core/target.d.ts +34 -5
  10. package/dist/firestore/src/lite-api/query.d.ts +2 -2
  11. package/dist/firestore/src/local/index_manager.d.ts +52 -0
  12. package/dist/firestore/src/local/indexeddb_index_manager.d.ts +11 -0
  13. package/dist/firestore/src/local/indexeddb_schema.d.ts +121 -7
  14. package/dist/firestore/src/local/local_serializer.d.ts +1 -1
  15. package/dist/firestore/src/local/memory_index_manager.d.ts +11 -0
  16. package/dist/firestore/src/local/remote_document_change_buffer.d.ts +3 -12
  17. package/dist/firestore/src/model/document.d.ts +7 -0
  18. package/dist/firestore/src/model/document_key.d.ts +1 -0
  19. package/dist/firestore/src/model/field_index.d.ts +156 -0
  20. package/dist/firestore/src/model/values.d.ts +7 -0
  21. package/dist/firestore/test/integration/api/index_configuration.test.d.ts +17 -0
  22. package/dist/firestore/test/unit/local/test_remote_document_cache.d.ts +1 -1
  23. package/dist/firestore/test/unit/model/field_index.test.d.ts +17 -0
  24. package/dist/firestore/test/unit/model/target.test.d.ts +17 -0
  25. package/dist/firestore/test/util/helpers.d.ts +8 -2
  26. package/dist/index.d.ts +16 -11
  27. package/dist/index.esm2017.js +2979 -2671
  28. package/dist/index.esm2017.js.map +1 -1
  29. package/dist/index.esm5.js +3036 -2815
  30. package/dist/index.esm5.js.map +1 -1
  31. package/dist/index.node.cjs.js +644 -235
  32. package/dist/index.node.cjs.js.map +1 -1
  33. package/dist/index.node.mjs +644 -236
  34. package/dist/index.node.mjs.map +1 -1
  35. package/dist/index.rn.js +2761 -2449
  36. package/dist/index.rn.js.map +1 -1
  37. package/dist/internal.d.ts +303 -25
  38. package/dist/lite/firestore/src/api/database.d.ts +14 -9
  39. package/dist/lite/firestore/src/api/{query.d.ts → filter.d.ts} +0 -0
  40. package/dist/lite/firestore/src/api/index_configuration.d.ts +117 -0
  41. package/dist/lite/firestore/src/api/snapshot.d.ts +1 -2
  42. package/dist/lite/firestore/src/api.d.ts +2 -1
  43. package/dist/lite/firestore/src/core/database_info.d.ts +1 -0
  44. package/dist/lite/firestore/src/core/firestore_client.d.ts +2 -0
  45. package/dist/lite/firestore/src/core/target.d.ts +34 -5
  46. package/dist/lite/firestore/src/lite-api/query.d.ts +2 -2
  47. package/dist/lite/firestore/src/local/index_manager.d.ts +52 -0
  48. package/dist/lite/firestore/src/local/indexeddb_index_manager.d.ts +11 -0
  49. package/dist/lite/firestore/src/local/indexeddb_schema.d.ts +121 -7
  50. package/dist/lite/firestore/src/local/local_serializer.d.ts +1 -1
  51. package/dist/lite/firestore/src/local/memory_index_manager.d.ts +11 -0
  52. package/dist/lite/firestore/src/local/remote_document_change_buffer.d.ts +3 -12
  53. package/dist/lite/firestore/src/model/document.d.ts +7 -0
  54. package/dist/lite/firestore/src/model/document_key.d.ts +1 -0
  55. package/dist/lite/firestore/src/model/field_index.d.ts +156 -0
  56. package/dist/lite/firestore/src/model/values.d.ts +7 -0
  57. package/dist/lite/firestore/test/integration/api/index_configuration.test.d.ts +17 -0
  58. package/dist/lite/firestore/test/unit/local/test_remote_document_cache.d.ts +1 -1
  59. package/dist/lite/firestore/test/unit/model/field_index.test.d.ts +17 -0
  60. package/dist/lite/firestore/test/unit/model/target.test.d.ts +17 -0
  61. package/dist/lite/firestore/test/util/helpers.d.ts +8 -2
  62. package/dist/lite/index.browser.esm2017.js +352 -338
  63. package/dist/lite/index.browser.esm2017.js.map +1 -1
  64. package/dist/lite/index.browser.esm5.js +334 -326
  65. package/dist/lite/index.browser.esm5.js.map +1 -1
  66. package/dist/lite/index.node.cjs.js +53 -34
  67. package/dist/lite/index.node.cjs.js.map +1 -1
  68. package/dist/lite/index.node.mjs +53 -34
  69. package/dist/lite/index.node.mjs.map +1 -1
  70. package/dist/lite/index.rn.esm2017.js +318 -304
  71. package/dist/lite/index.rn.esm2017.js.map +1 -1
  72. package/dist/lite/internal.d.ts +11 -2
  73. package/dist/lite/packages/firestore/dist/lite/index.browser.esm2017.d.ts +98 -97
  74. package/dist/lite/packages/firestore/src/api/database.d.ts +14 -9
  75. package/dist/lite/packages/firestore/src/api/{query.d.ts → filter.d.ts} +0 -0
  76. package/dist/lite/packages/firestore/src/api/index_configuration.d.ts +117 -0
  77. package/dist/lite/packages/firestore/src/api/snapshot.d.ts +1 -2
  78. package/dist/lite/packages/firestore/src/api.d.ts +2 -1
  79. package/dist/lite/packages/firestore/src/core/database_info.d.ts +1 -0
  80. package/dist/lite/packages/firestore/src/core/firestore_client.d.ts +2 -0
  81. package/dist/lite/packages/firestore/src/core/target.d.ts +34 -5
  82. package/dist/lite/packages/firestore/src/lite-api/query.d.ts +2 -2
  83. package/dist/lite/packages/firestore/src/local/index_manager.d.ts +52 -0
  84. package/dist/lite/packages/firestore/src/local/indexeddb_index_manager.d.ts +11 -0
  85. package/dist/lite/packages/firestore/src/local/indexeddb_schema.d.ts +121 -7
  86. package/dist/lite/packages/firestore/src/local/local_serializer.d.ts +1 -1
  87. package/dist/lite/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
  88. package/dist/lite/packages/firestore/src/local/remote_document_change_buffer.d.ts +3 -12
  89. package/dist/lite/packages/firestore/src/model/document.d.ts +7 -0
  90. package/dist/lite/packages/firestore/src/model/document_key.d.ts +1 -0
  91. package/dist/lite/packages/firestore/src/model/field_index.d.ts +156 -0
  92. package/dist/lite/packages/firestore/src/model/values.d.ts +7 -0
  93. package/dist/lite/packages/firestore/test/integration/api/index_configuration.test.d.ts +17 -0
  94. package/dist/lite/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +1 -1
  95. package/dist/lite/packages/firestore/test/unit/model/field_index.test.d.ts +17 -0
  96. package/dist/lite/packages/firestore/test/unit/model/target.test.d.ts +17 -0
  97. package/dist/lite/packages/firestore/test/util/helpers.d.ts +8 -2
  98. package/dist/lite/private.d.ts +9 -2
  99. package/dist/packages/firestore/dist/index.esm2017.d.ts +214 -191
  100. package/dist/packages/firestore/src/api/database.d.ts +14 -9
  101. package/dist/packages/firestore/src/api/{query.d.ts → filter.d.ts} +0 -0
  102. package/dist/packages/firestore/src/api/index_configuration.d.ts +117 -0
  103. package/dist/packages/firestore/src/api/snapshot.d.ts +1 -2
  104. package/dist/packages/firestore/src/api.d.ts +2 -1
  105. package/dist/packages/firestore/src/core/database_info.d.ts +1 -0
  106. package/dist/packages/firestore/src/core/firestore_client.d.ts +2 -0
  107. package/dist/packages/firestore/src/core/target.d.ts +34 -5
  108. package/dist/packages/firestore/src/lite-api/query.d.ts +2 -2
  109. package/dist/packages/firestore/src/local/index_manager.d.ts +52 -0
  110. package/dist/packages/firestore/src/local/indexeddb_index_manager.d.ts +11 -0
  111. package/dist/packages/firestore/src/local/indexeddb_schema.d.ts +121 -7
  112. package/dist/packages/firestore/src/local/local_serializer.d.ts +1 -1
  113. package/dist/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
  114. package/dist/packages/firestore/src/local/remote_document_change_buffer.d.ts +3 -12
  115. package/dist/packages/firestore/src/model/document.d.ts +7 -0
  116. package/dist/packages/firestore/src/model/document_key.d.ts +1 -0
  117. package/dist/packages/firestore/src/model/field_index.d.ts +156 -0
  118. package/dist/packages/firestore/src/model/values.d.ts +7 -0
  119. package/dist/packages/firestore/test/integration/api/index_configuration.test.d.ts +17 -0
  120. package/dist/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +1 -1
  121. package/dist/packages/firestore/test/unit/model/field_index.test.d.ts +17 -0
  122. package/dist/packages/firestore/test/unit/model/target.test.d.ts +17 -0
  123. package/dist/packages/firestore/test/util/helpers.d.ts +8 -2
  124. package/dist/private.d.ts +205 -25
  125. package/package.json +10 -10
@@ -12,7 +12,7 @@ var grpcJs = require('@grpc/grpc-js');
12
12
  var protoLoader = require('@grpc/proto-loader');
13
13
 
14
14
  const name = "@firebase/firestore";
15
- const version$1 = "3.4.3";
15
+ const version$1 = "3.4.4-canary.0482aa5b7";
16
16
 
17
17
  /**
18
18
  * @license
@@ -65,7 +65,7 @@ User.GOOGLE_CREDENTIALS = new User('google-credentials-uid');
65
65
  User.FIRST_PARTY = new User('first-party-uid');
66
66
  User.MOCK_USER = new User('mock-user');
67
67
 
68
- const version = "9.6.3";
68
+ const version = "9.6.5-canary.0482aa5b7";
69
69
 
70
70
  /**
71
71
  * @license
@@ -1196,23 +1196,6 @@ function decodeResourcePath(path) {
1196
1196
  }
1197
1197
  return new ResourcePath(segments);
1198
1198
  }
1199
-
1200
- /**
1201
- * @license
1202
- * Copyright 2017 Google LLC
1203
- *
1204
- * Licensed under the Apache License, Version 2.0 (the "License");
1205
- * you may not use this file except in compliance with the License.
1206
- * You may obtain a copy of the License at
1207
- *
1208
- * http://www.apache.org/licenses/LICENSE-2.0
1209
- *
1210
- * Unless required by applicable law or agreed to in writing, software
1211
- * distributed under the License is distributed on an "AS IS" BASIS,
1212
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1213
- * See the License for the specific language governing permissions and
1214
- * limitations under the License.
1215
- */
1216
1199
  /**
1217
1200
  * Schema Version for the Web client:
1218
1201
  * 1. Initial version including Mutation Queue, Query Cache, and Remote
@@ -1231,6 +1214,7 @@ function decodeResourcePath(path) {
1231
1214
  * an auto-incrementing ID. This is required for Index-Free queries.
1232
1215
  * 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
1233
1216
  * 11. Add bundles and named_queries for bundle support.
1217
+ * 12. Add indexing support.
1234
1218
  */
1235
1219
  const SCHEMA_VERSION = 11;
1236
1220
  /**
@@ -1757,9 +1741,7 @@ class DbClientMetadata {
1757
1741
  DbClientMetadata.store = 'clientMetadata';
1758
1742
  /** Keys are automatically assigned via the clientId properties. */
1759
1743
  DbClientMetadata.keyPath = 'clientId';
1760
- /**
1761
- * A object representing a bundle loaded by the SDK.
1762
- */
1744
+ /** An object representing a bundle loaded by the SDK. */
1763
1745
  class DbBundle {
1764
1746
  constructor(
1765
1747
  /** The ID of the loaded bundle. */
@@ -1776,9 +1758,7 @@ class DbBundle {
1776
1758
  /** Name of the IndexedDb object store. */
1777
1759
  DbBundle.store = 'bundles';
1778
1760
  DbBundle.keyPath = 'bundleId';
1779
- /**
1780
- * A object representing a named query loaded by the SDK via a bundle.
1781
- */
1761
+ /** An object representing a named query loaded by the SDK via a bundle. */
1782
1762
  class DbNamedQuery {
1783
1763
  constructor(
1784
1764
  /** The name of the query. */
@@ -1795,6 +1775,93 @@ class DbNamedQuery {
1795
1775
  /** Name of the IndexedDb object store. */
1796
1776
  DbNamedQuery.store = 'namedQueries';
1797
1777
  DbNamedQuery.keyPath = 'name';
1778
+ /** An object representing the global configuration for a field index. */
1779
+ class DbIndexConfiguration {
1780
+ constructor(
1781
+ /** The index id for this entry. */
1782
+ indexId,
1783
+ /** The collection group this index belongs to. */
1784
+ collectionGroup,
1785
+ /** The fields to index for this index. */
1786
+ fields) {
1787
+ this.indexId = indexId;
1788
+ this.collectionGroup = collectionGroup;
1789
+ this.fields = fields;
1790
+ }
1791
+ }
1792
+ /** Name of the IndexedDb object store. */
1793
+ DbIndexConfiguration.store = 'indexConfiguration';
1794
+ DbIndexConfiguration.keyPath = 'indexId';
1795
+ /**
1796
+ * An object describing how up-to-date the index backfill is for each user and
1797
+ * index.
1798
+ */
1799
+ class DbIndexState {
1800
+ constructor(
1801
+ /** The index id for this entry. */
1802
+ indexId,
1803
+ /** The user id for this entry. */
1804
+ uid,
1805
+ /**
1806
+ * A number that indicates when the index was last updated (relative to
1807
+ * other indexes).
1808
+ */
1809
+ sequenceNumber,
1810
+ /**
1811
+ * The latest read time that has been indexed by Firestore for this field
1812
+ * index. Set to `{seconds: 0, nanos: 0}` if no documents have been indexed.
1813
+ */
1814
+ readTime,
1815
+ /**
1816
+ * The last document that has been indexed for this field index. Empty if
1817
+ * no documents have been indexed.
1818
+ */
1819
+ documentKey,
1820
+ /**
1821
+ * The largest mutation batch id that has been processed for this index. -1
1822
+ * if no mutations have been indexed.
1823
+ */
1824
+ largestBatchId) {
1825
+ this.indexId = indexId;
1826
+ this.uid = uid;
1827
+ this.sequenceNumber = sequenceNumber;
1828
+ this.readTime = readTime;
1829
+ this.documentKey = documentKey;
1830
+ this.largestBatchId = largestBatchId;
1831
+ }
1832
+ }
1833
+ /** Name of the IndexedDb object store. */
1834
+ DbIndexState.store = 'indexState';
1835
+ DbIndexState.keyPath = ['indexId', 'uid'];
1836
+ /** An object that stores the encoded entries for all documents and fields. */
1837
+ class DbIndexEntries {
1838
+ constructor(
1839
+ /** The index id for this entry. */
1840
+ indexId,
1841
+ /** The user id for this entry. */
1842
+ uid,
1843
+ /** The encoded array index value for this entry. */
1844
+ arrayValue,
1845
+ /** The encoded directional value for equality and inequality filters. */
1846
+ directionalValue,
1847
+ /** The document key this entry points to. */
1848
+ documentKey) {
1849
+ this.indexId = indexId;
1850
+ this.uid = uid;
1851
+ this.arrayValue = arrayValue;
1852
+ this.directionalValue = directionalValue;
1853
+ this.documentKey = documentKey;
1854
+ }
1855
+ }
1856
+ /** Name of the IndexedDb object store. */
1857
+ DbIndexEntries.store = 'indexEntries';
1858
+ DbIndexEntries.keyPath = [
1859
+ 'indexId',
1860
+ 'uid',
1861
+ 'arrayValue',
1862
+ 'directionalValue',
1863
+ 'documentKey'
1864
+ ];
1798
1865
  // Visible for testing
1799
1866
  const V1_STORES = [
1800
1867
  DbMutationQueue.store,
@@ -1809,7 +1876,6 @@ const V1_STORES = [
1809
1876
  // V2 is no longer usable (see comment at top of file)
1810
1877
  // Visible for testing
1811
1878
  const V3_STORES = V1_STORES;
1812
- // Visible for testing
1813
1879
  // Note: DbRemoteDocumentChanges is no longer used and dropped with v9.
1814
1880
  const V4_STORES = [...V3_STORES, DbClientMetadata.store];
1815
1881
  // V5 does not change the set of stores.
@@ -1819,6 +1885,12 @@ const V8_STORES = [...V6_STORES, DbCollectionParent.store];
1819
1885
  // V9 does not change the set of stores.
1820
1886
  // V10 does not change the set of stores.
1821
1887
  const V11_STORES = [...V8_STORES, DbBundle.store, DbNamedQuery.store];
1888
+ [
1889
+ ...V11_STORES,
1890
+ DbIndexConfiguration.store,
1891
+ DbIndexState.store,
1892
+ DbIndexEntries.store
1893
+ ];
1822
1894
  /**
1823
1895
  * The list of all default IndexedDB stores used throughout the SDK. This is
1824
1896
  * used when creating transactions so that access across all stores is done
@@ -3378,6 +3450,75 @@ function getLocalWriteTime(value) {
3378
3450
  return new Timestamp(localWriteTime.seconds, localWriteTime.nanos);
3379
3451
  }
3380
3452
 
3453
+ /**
3454
+ * @license
3455
+ * Copyright 2017 Google LLC
3456
+ *
3457
+ * Licensed under the Apache License, Version 2.0 (the "License");
3458
+ * you may not use this file except in compliance with the License.
3459
+ * You may obtain a copy of the License at
3460
+ *
3461
+ * http://www.apache.org/licenses/LICENSE-2.0
3462
+ *
3463
+ * Unless required by applicable law or agreed to in writing, software
3464
+ * distributed under the License is distributed on an "AS IS" BASIS,
3465
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3466
+ * See the License for the specific language governing permissions and
3467
+ * limitations under the License.
3468
+ */
3469
+ class DatabaseInfo {
3470
+ /**
3471
+ * Constructs a DatabaseInfo using the provided host, databaseId and
3472
+ * persistenceKey.
3473
+ *
3474
+ * @param databaseId - The database to use.
3475
+ * @param appId - The Firebase App Id.
3476
+ * @param persistenceKey - A unique identifier for this Firestore's local
3477
+ * storage (used in conjunction with the databaseId).
3478
+ * @param host - The Firestore backend host to connect to.
3479
+ * @param ssl - Whether to use SSL when connecting.
3480
+ * @param forceLongPolling - Whether to use the forceLongPolling option
3481
+ * when using WebChannel as the network transport.
3482
+ * @param autoDetectLongPolling - Whether to use the detectBufferingProxy
3483
+ * option when using WebChannel as the network transport.
3484
+ * @param useFetchStreams Whether to use the Fetch API instead of
3485
+ * XMLHTTPRequest
3486
+ */
3487
+ constructor(databaseId, appId, persistenceKey, host, ssl, forceLongPolling, autoDetectLongPolling, useFetchStreams) {
3488
+ this.databaseId = databaseId;
3489
+ this.appId = appId;
3490
+ this.persistenceKey = persistenceKey;
3491
+ this.host = host;
3492
+ this.ssl = ssl;
3493
+ this.forceLongPolling = forceLongPolling;
3494
+ this.autoDetectLongPolling = autoDetectLongPolling;
3495
+ this.useFetchStreams = useFetchStreams;
3496
+ }
3497
+ }
3498
+ /** The default database name for a project. */
3499
+ const DEFAULT_DATABASE_NAME = '(default)';
3500
+ /**
3501
+ * Represents the database ID a Firestore client is associated with.
3502
+ * @internal
3503
+ */
3504
+ class DatabaseId {
3505
+ constructor(projectId, database) {
3506
+ this.projectId = projectId;
3507
+ this.database = database ? database : DEFAULT_DATABASE_NAME;
3508
+ }
3509
+ static empty() {
3510
+ return new DatabaseId('', '');
3511
+ }
3512
+ get isDefaultDatabase() {
3513
+ return this.database === DEFAULT_DATABASE_NAME;
3514
+ }
3515
+ isEqual(other) {
3516
+ return (other instanceof DatabaseId &&
3517
+ other.projectId === this.projectId &&
3518
+ other.database === this.database);
3519
+ }
3520
+ }
3521
+
3381
3522
  /**
3382
3523
  * @license
3383
3524
  * Copyright 2017 Google LLC
@@ -3449,6 +3590,9 @@ class DocumentKey {
3449
3590
  static fromName(name) {
3450
3591
  return new DocumentKey(ResourcePath.fromString(name).popFirst(5));
3451
3592
  }
3593
+ static empty() {
3594
+ return new DocumentKey(ResourcePath.emptyPath());
3595
+ }
3452
3596
  /** Returns true if the document is in the specified collectionId. */
3453
3597
  hasCollectionId(collectionId) {
3454
3598
  return (this.path.length >= 2 &&
@@ -4097,10 +4241,11 @@ function extractFieldMask(value) {
4097
4241
  * from all views.
4098
4242
  */
4099
4243
  class MutableDocument {
4100
- constructor(key, documentType, version, data, documentState) {
4244
+ constructor(key, documentType, version, readTime, data, documentState) {
4101
4245
  this.key = key;
4102
4246
  this.documentType = documentType;
4103
4247
  this.version = version;
4248
+ this.readTime = readTime;
4104
4249
  this.data = data;
4105
4250
  this.documentState = documentState;
4106
4251
  }
@@ -4109,18 +4254,18 @@ class MutableDocument {
4109
4254
  * base document for mutations.
4110
4255
  */
4111
4256
  static newInvalidDocument(documentKey) {
4112
- return new MutableDocument(documentKey, 0 /* INVALID */, SnapshotVersion.min(), ObjectValue.empty(), 0 /* SYNCED */);
4257
+ return new MutableDocument(documentKey, 0 /* INVALID */, SnapshotVersion.min(), SnapshotVersion.min(), ObjectValue.empty(), 0 /* SYNCED */);
4113
4258
  }
4114
4259
  /**
4115
4260
  * Creates a new document that is known to exist with the given data at the
4116
4261
  * given version.
4117
4262
  */
4118
4263
  static newFoundDocument(documentKey, version, value) {
4119
- return new MutableDocument(documentKey, 1 /* FOUND_DOCUMENT */, version, value, 0 /* SYNCED */);
4264
+ return new MutableDocument(documentKey, 1 /* FOUND_DOCUMENT */, version, SnapshotVersion.min(), value, 0 /* SYNCED */);
4120
4265
  }
4121
4266
  /** Creates a new document that is known to not exist at the given version. */
4122
4267
  static newNoDocument(documentKey, version) {
4123
- return new MutableDocument(documentKey, 2 /* NO_DOCUMENT */, version, ObjectValue.empty(), 0 /* SYNCED */);
4268
+ return new MutableDocument(documentKey, 2 /* NO_DOCUMENT */, version, SnapshotVersion.min(), ObjectValue.empty(), 0 /* SYNCED */);
4124
4269
  }
4125
4270
  /**
4126
4271
  * Creates a new document that is known to exist at the given version but
@@ -4128,7 +4273,7 @@ class MutableDocument {
4128
4273
  * base document).
4129
4274
  */
4130
4275
  static newUnknownDocument(documentKey, version) {
4131
- return new MutableDocument(documentKey, 3 /* UNKNOWN_DOCUMENT */, version, ObjectValue.empty(), 2 /* HAS_COMMITTED_MUTATIONS */);
4276
+ return new MutableDocument(documentKey, 3 /* UNKNOWN_DOCUMENT */, version, SnapshotVersion.min(), ObjectValue.empty(), 2 /* HAS_COMMITTED_MUTATIONS */);
4132
4277
  }
4133
4278
  /**
4134
4279
  * Changes the document type to indicate that it exists and that its version
@@ -4172,6 +4317,10 @@ class MutableDocument {
4172
4317
  this.documentState = 1 /* HAS_LOCAL_MUTATIONS */;
4173
4318
  return this;
4174
4319
  }
4320
+ setReadTime(readTime) {
4321
+ this.readTime = readTime;
4322
+ return this;
4323
+ }
4175
4324
  get hasLocalMutations() {
4176
4325
  return this.documentState === 1 /* HAS_LOCAL_MUTATIONS */;
4177
4326
  }
@@ -4202,7 +4351,7 @@ class MutableDocument {
4202
4351
  this.data.isEqual(other.data));
4203
4352
  }
4204
4353
  mutableCopy() {
4205
- return new MutableDocument(this.key, this.documentType, this.version, this.data.clone(), this.documentState);
4354
+ return new MutableDocument(this.key, this.documentType, this.version, this.readTime, this.data.clone(), this.documentState);
4206
4355
  }
4207
4356
  toString() {
4208
4357
  return (`Document(${this.key}, ${this.version}, ${JSON.stringify(this.data.value)}, ` +
@@ -4225,6 +4374,125 @@ function compareDocumentsByField(field, d1, d2) {
4225
4374
  }
4226
4375
  }
4227
4376
 
4377
+ /**
4378
+ * @license
4379
+ * Copyright 2021 Google LLC
4380
+ *
4381
+ * Licensed under the Apache License, Version 2.0 (the "License");
4382
+ * you may not use this file except in compliance with the License.
4383
+ * You may obtain a copy of the License at
4384
+ *
4385
+ * http://www.apache.org/licenses/LICENSE-2.0
4386
+ *
4387
+ * Unless required by applicable law or agreed to in writing, software
4388
+ * distributed under the License is distributed on an "AS IS" BASIS,
4389
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4390
+ * See the License for the specific language governing permissions and
4391
+ * limitations under the License.
4392
+ */
4393
+ /**
4394
+ * The initial mutation batch id for each index. Gets updated during index
4395
+ * backfill.
4396
+ */
4397
+ const INITIAL_LARGEST_BATCH_ID = -1;
4398
+ /**
4399
+ * The initial sequence number for each index. Gets updated during index
4400
+ * backfill.
4401
+ */
4402
+ const INITIAL_SEQUENCE_NUMBER = 0;
4403
+ /**
4404
+ * An index definition for field indexes in Firestore.
4405
+ *
4406
+ * Every index is associated with a collection. The definition contains a list
4407
+ * of fields and their index kind (which can be `ASCENDING`, `DESCENDING` or
4408
+ * `CONTAINS` for ArrayContains/ArrayContainsAny queries).
4409
+ *
4410
+ * Unlike the backend, the SDK does not differentiate between collection or
4411
+ * collection group-scoped indices. Every index can be used for both single
4412
+ * collection and collection group queries.
4413
+ */
4414
+ class FieldIndex {
4415
+ constructor(
4416
+ /**
4417
+ * The index ID. Returns -1 if the index ID is not available (e.g. the index
4418
+ * has not yet been persisted).
4419
+ */
4420
+ indexId,
4421
+ /** The collection ID this index applies to. */
4422
+ collectionGroup,
4423
+ /** The field segments for this index. */
4424
+ segments,
4425
+ /** Shows how up-to-date the index is for the current user. */
4426
+ indexState) {
4427
+ this.indexId = indexId;
4428
+ this.collectionGroup = collectionGroup;
4429
+ this.segments = segments;
4430
+ this.indexState = indexState;
4431
+ }
4432
+ }
4433
+ /** An ID for an index that has not yet been added to persistence. */
4434
+ FieldIndex.UNKNOWN_ID = -1;
4435
+ /** An index component consisting of field path and index type. */
4436
+ class IndexSegment {
4437
+ constructor(
4438
+ /** The field path of the component. */
4439
+ fieldPath,
4440
+ /** The fields sorting order. */
4441
+ kind) {
4442
+ this.fieldPath = fieldPath;
4443
+ this.kind = kind;
4444
+ }
4445
+ }
4446
+ /**
4447
+ * Stores the "high water mark" that indicates how updated the Index is for the
4448
+ * current user.
4449
+ */
4450
+ class IndexState {
4451
+ constructor(
4452
+ /**
4453
+ * Indicates when the index was last updated (relative to other indexes).
4454
+ */
4455
+ sequenceNumber,
4456
+ /** The the latest indexed read time, document and batch id. */
4457
+ offset) {
4458
+ this.sequenceNumber = sequenceNumber;
4459
+ this.offset = offset;
4460
+ }
4461
+ /** The state of an index that has not yet been backfilled. */
4462
+ static empty() {
4463
+ return new IndexState(INITIAL_SEQUENCE_NUMBER, IndexOffset.min());
4464
+ }
4465
+ }
4466
+ /**
4467
+ * Stores the latest read time, document and batch ID that were processed for an
4468
+ * index.
4469
+ */
4470
+ class IndexOffset {
4471
+ constructor(
4472
+ /**
4473
+ * The latest read time version that has been indexed by Firestore for this
4474
+ * field index.
4475
+ */
4476
+ readTime,
4477
+ /**
4478
+ * The key of the last document that was indexed for this query. Use
4479
+ * `DocumentKey.empty()` if no document has been indexed.
4480
+ */
4481
+ documentKey,
4482
+ /*
4483
+ * The largest mutation batch id that's been processed by Firestore.
4484
+ */
4485
+ largestBatchId) {
4486
+ this.readTime = readTime;
4487
+ this.documentKey = documentKey;
4488
+ this.largestBatchId = largestBatchId;
4489
+ }
4490
+ /** The state of an index that has not yet been backfilled. */
4491
+ static min() {
4492
+ return new IndexOffset(SnapshotVersion.min(), DocumentKey.empty(), INITIAL_LARGEST_BATCH_ID);
4493
+ }
4494
+ }
4495
+
4228
4496
  /**
4229
4497
  * @license
4230
4498
  * Copyright 2019 Google LLC
@@ -4268,27 +4536,29 @@ function newTarget(path, collectionGroup = null, orderBy = [], filters = [], lim
4268
4536
  function canonifyTarget(target) {
4269
4537
  const targetImpl = debugCast(target);
4270
4538
  if (targetImpl.memoizedCanonicalId === null) {
4271
- let canonicalId = targetImpl.path.canonicalString();
4539
+ let str = targetImpl.path.canonicalString();
4272
4540
  if (targetImpl.collectionGroup !== null) {
4273
- canonicalId += '|cg:' + targetImpl.collectionGroup;
4541
+ str += '|cg:' + targetImpl.collectionGroup;
4274
4542
  }
4275
- canonicalId += '|f:';
4276
- canonicalId += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
4277
- canonicalId += '|ob:';
4278
- canonicalId += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
4543
+ str += '|f:';
4544
+ str += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
4545
+ str += '|ob:';
4546
+ str += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
4279
4547
  if (!isNullOrUndefined(targetImpl.limit)) {
4280
- canonicalId += '|l:';
4281
- canonicalId += targetImpl.limit;
4548
+ str += '|l:';
4549
+ str += targetImpl.limit;
4282
4550
  }
4283
4551
  if (targetImpl.startAt) {
4284
- canonicalId += '|lb:';
4285
- canonicalId += canonifyBound(targetImpl.startAt);
4552
+ str += '|lb:';
4553
+ str += targetImpl.startAt.inclusive ? 'b:' : 'a:';
4554
+ str += targetImpl.startAt.position.map(p => canonicalId(p)).join(',');
4286
4555
  }
4287
4556
  if (targetImpl.endAt) {
4288
- canonicalId += '|ub:';
4289
- canonicalId += canonifyBound(targetImpl.endAt);
4557
+ str += '|ub:';
4558
+ str += targetImpl.endAt.inclusive ? 'a:' : 'b:';
4559
+ str += targetImpl.endAt.position.map(p => canonicalId(p)).join(',');
4290
4560
  }
4291
- targetImpl.memoizedCanonicalId = canonicalId;
4561
+ targetImpl.memoizedCanonicalId = str;
4292
4562
  }
4293
4563
  return targetImpl.memoizedCanonicalId;
4294
4564
  }
@@ -4311,10 +4581,14 @@ function stringifyTarget(target) {
4311
4581
  .join(', ')}]`;
4312
4582
  }
4313
4583
  if (target.startAt) {
4314
- str += ', startAt: ' + canonifyBound(target.startAt);
4584
+ str += ', startAt: ';
4585
+ str += target.startAt.inclusive ? 'b:' : 'a:';
4586
+ str += target.startAt.position.map(p => canonicalId(p)).join(',');
4315
4587
  }
4316
4588
  if (target.endAt) {
4317
- str += ', endAt: ' + canonifyBound(target.endAt);
4589
+ str += ', endAt: ';
4590
+ str += target.endAt.inclusive ? 'a:' : 'b:';
4591
+ str += target.endAt.position.map(p => canonicalId(p)).join(',');
4318
4592
  }
4319
4593
  return `Target(${str})`;
4320
4594
  }
@@ -4349,7 +4623,7 @@ function targetEquals(left, right) {
4349
4623
  }
4350
4624
  return boundEquals(left.endAt, right.endAt);
4351
4625
  }
4352
- function isDocumentTarget(target) {
4626
+ function targetIsDocumentTarget(target) {
4353
4627
  return (DocumentKey.isDocumentKey(target.path) &&
4354
4628
  target.collectionGroup === null &&
4355
4629
  target.filters.length === 0);
@@ -4552,17 +4826,11 @@ class ArrayContainsAnyFilter extends FieldFilter {
4552
4826
  * just after the provided values.
4553
4827
  */
4554
4828
  class Bound {
4555
- constructor(position, before) {
4829
+ constructor(position, inclusive) {
4556
4830
  this.position = position;
4557
- this.before = before;
4831
+ this.inclusive = inclusive;
4558
4832
  }
4559
4833
  }
4560
- function canonifyBound(bound) {
4561
- // TODO(b/29183165): Make this collision robust.
4562
- return `${bound.before ? 'b' : 'a'}:${bound.position
4563
- .map(p => canonicalId(p))
4564
- .join(',')}`;
4565
- }
4566
4834
  /**
4567
4835
  * An ordering on a field, in some Direction. Direction defaults to ASCENDING.
4568
4836
  */
@@ -4582,11 +4850,7 @@ function stringifyOrderBy(orderBy) {
4582
4850
  function orderByEquals(left, right) {
4583
4851
  return left.dir === right.dir && left.field.isEqual(right.field);
4584
4852
  }
4585
- /**
4586
- * Returns true if a document sorts before a bound using the provided sort
4587
- * order.
4588
- */
4589
- function sortsBeforeDocument(bound, orderBy, doc) {
4853
+ function boundCompareToDocument(bound, orderBy, doc) {
4590
4854
  let comparison = 0;
4591
4855
  for (let i = 0; i < bound.position.length; i++) {
4592
4856
  const orderByComponent = orderBy[i];
@@ -4605,7 +4869,23 @@ function sortsBeforeDocument(bound, orderBy, doc) {
4605
4869
  break;
4606
4870
  }
4607
4871
  }
4608
- return bound.before ? comparison <= 0 : comparison < 0;
4872
+ return comparison;
4873
+ }
4874
+ /**
4875
+ * Returns true if a document sorts after a bound using the provided sort
4876
+ * order.
4877
+ */
4878
+ function boundSortsAfterDocument(bound, orderBy, doc) {
4879
+ const comparison = boundCompareToDocument(bound, orderBy, doc);
4880
+ return bound.inclusive ? comparison >= 0 : comparison > 0;
4881
+ }
4882
+ /**
4883
+ * Returns true if a document sorts before a bound using the provided sort
4884
+ * order.
4885
+ */
4886
+ function boundSortsBeforeDocument(bound, orderBy, doc) {
4887
+ const comparison = boundCompareToDocument(bound, orderBy, doc);
4888
+ return bound.inclusive ? comparison <= 0 : comparison < 0;
4609
4889
  }
4610
4890
  function boundEquals(left, right) {
4611
4891
  if (left === null) {
@@ -4614,7 +4894,7 @@ function boundEquals(left, right) {
4614
4894
  else if (right === null) {
4615
4895
  return false;
4616
4896
  }
4617
- if (left.before !== right.before ||
4897
+ if (left.inclusive !== right.inclusive ||
4618
4898
  left.position.length !== right.position.length) {
4619
4899
  return false;
4620
4900
  }
@@ -4818,10 +5098,10 @@ function queryToTarget(query) {
4818
5098
  }
4819
5099
  // We need to swap the cursors to match the now-flipped query ordering.
4820
5100
  const startAt = queryImpl.endAt
4821
- ? new Bound(queryImpl.endAt.position, !queryImpl.endAt.before)
5101
+ ? new Bound(queryImpl.endAt.position, !queryImpl.endAt.inclusive)
4822
5102
  : null;
4823
5103
  const endAt = queryImpl.startAt
4824
- ? new Bound(queryImpl.startAt.position, !queryImpl.startAt.before)
5104
+ ? new Bound(queryImpl.startAt.position, !queryImpl.startAt.inclusive)
4825
5105
  : null;
4826
5106
  // Now return as a LimitType.First query.
4827
5107
  queryImpl.memoizedTarget = newTarget(queryImpl.path, queryImpl.collectionGroup, orderBys, queryImpl.filters, queryImpl.limit, startAt, endAt);
@@ -4909,11 +5189,11 @@ function queryMatchesFilters(query, doc) {
4909
5189
  /** Makes sure a document is within the bounds, if provided. */
4910
5190
  function queryMatchesBounds(query, doc) {
4911
5191
  if (query.startAt &&
4912
- !sortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
5192
+ !boundSortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
4913
5193
  return false;
4914
5194
  }
4915
5195
  if (query.endAt &&
4916
- sortsBeforeDocument(query.endAt, queryOrderBy(query), doc)) {
5196
+ !boundSortsAfterDocument(query.endAt, queryOrderBy(query), doc)) {
4917
5197
  return false;
4918
5198
  }
4919
5199
  return true;
@@ -6994,7 +7274,7 @@ class WatchChangeAggregator {
6994
7274
  const targetData = this.targetDataForActiveTarget(targetId);
6995
7275
  if (targetData) {
6996
7276
  const target = targetData.target;
6997
- if (isDocumentTarget(target)) {
7277
+ if (targetIsDocumentTarget(target)) {
6998
7278
  if (expectedCount === 0) {
6999
7279
  // The existence filter told us the document does not exist. We deduce
7000
7280
  // that this document does not exist and apply a deleted document to
@@ -7029,7 +7309,7 @@ class WatchChangeAggregator {
7029
7309
  this.targetStates.forEach((targetState, targetId) => {
7030
7310
  const targetData = this.targetDataForActiveTarget(targetId);
7031
7311
  if (targetData) {
7032
- if (targetState.current && isDocumentTarget(targetData.target)) {
7312
+ if (targetState.current && targetIsDocumentTarget(targetData.target)) {
7033
7313
  // Document queries for document that don't exist can produce an empty
7034
7314
  // result set. To update our local cache, we synthesize a document
7035
7315
  // delete if we have not previously received the document. This
@@ -7072,6 +7352,7 @@ class WatchChangeAggregator {
7072
7352
  resolvedLimboDocuments = resolvedLimboDocuments.add(key);
7073
7353
  }
7074
7354
  });
7355
+ this.pendingDocumentUpdates.forEach((_, doc) => doc.setReadTime(snapshotVersion));
7075
7356
  const remoteEvent = new RemoteEvent(snapshotVersion, targetChanges, this.pendingTargetResets, this.pendingDocumentUpdates, resolvedLimboDocuments);
7076
7357
  this.pendingDocumentUpdates = mutableDocumentMap();
7077
7358
  this.pendingDocumentTargetMapping = documentTargetMap();
@@ -7791,10 +8072,10 @@ function toQueryTarget(serializer, target) {
7791
8072
  result.structuredQuery.limit = limit;
7792
8073
  }
7793
8074
  if (target.startAt) {
7794
- result.structuredQuery.startAt = toCursor(target.startAt);
8075
+ result.structuredQuery.startAt = toStartAtCursor(target.startAt);
7795
8076
  }
7796
8077
  if (target.endAt) {
7797
- result.structuredQuery.endAt = toCursor(target.endAt);
8078
+ result.structuredQuery.endAt = toEndAtCursor(target.endAt);
7798
8079
  }
7799
8080
  return result;
7800
8081
  }
@@ -7827,11 +8108,11 @@ function convertQueryTargetToQuery(target) {
7827
8108
  }
7828
8109
  let startAt = null;
7829
8110
  if (query.startAt) {
7830
- startAt = fromCursor(query.startAt);
8111
+ startAt = fromStartAtCursor(query.startAt);
7831
8112
  }
7832
8113
  let endAt = null;
7833
8114
  if (query.endAt) {
7834
- endAt = fromCursor(query.endAt);
8115
+ endAt = fromEndAtCursor(query.endAt);
7835
8116
  }
7836
8117
  return newQuery(path, collectionGroup, orderBy, filterBy, limit, "F" /* First */, startAt, endAt);
7837
8118
  }
@@ -7864,7 +8145,7 @@ function toLabel(serializer, purpose) {
7864
8145
  function toTarget(serializer, targetData) {
7865
8146
  let result;
7866
8147
  const target = targetData.target;
7867
- if (isDocumentTarget(target)) {
8148
+ if (targetIsDocumentTarget(target)) {
7868
8149
  result = { documents: toDocumentsTarget(serializer, target) };
7869
8150
  }
7870
8151
  else {
@@ -7922,16 +8203,27 @@ function toOrder(orderBys) {
7922
8203
  function fromOrder(orderBys) {
7923
8204
  return orderBys.map(order => fromPropertyOrder(order));
7924
8205
  }
7925
- function toCursor(cursor) {
8206
+ function toStartAtCursor(cursor) {
8207
+ return {
8208
+ before: cursor.inclusive,
8209
+ values: cursor.position
8210
+ };
8211
+ }
8212
+ function toEndAtCursor(cursor) {
7926
8213
  return {
7927
- before: cursor.before,
8214
+ before: !cursor.inclusive,
7928
8215
  values: cursor.position
7929
8216
  };
7930
8217
  }
7931
- function fromCursor(cursor) {
7932
- const before = !!cursor.before;
8218
+ function fromStartAtCursor(cursor) {
8219
+ const inclusive = !!cursor.before;
7933
8220
  const position = cursor.values || [];
7934
- return new Bound(position, before);
8221
+ return new Bound(position, inclusive);
8222
+ }
8223
+ function fromEndAtCursor(cursor) {
8224
+ const inclusive = !cursor.before;
8225
+ const position = cursor.values || [];
8226
+ return new Bound(position, inclusive);
7935
8227
  }
7936
8228
  // visible for testing
7937
8229
  function toDirection(dir) {
@@ -8192,29 +8484,34 @@ class LocalSerializer {
8192
8484
  }
8193
8485
  /** Decodes a remote document from storage locally to a Document. */
8194
8486
  function fromDbRemoteDocument(localSerializer, remoteDoc) {
8487
+ let doc;
8195
8488
  if (remoteDoc.document) {
8196
- return fromDocument(localSerializer.remoteSerializer, remoteDoc.document, !!remoteDoc.hasCommittedMutations);
8489
+ doc = fromDocument(localSerializer.remoteSerializer, remoteDoc.document, !!remoteDoc.hasCommittedMutations);
8197
8490
  }
8198
8491
  else if (remoteDoc.noDocument) {
8199
8492
  const key = DocumentKey.fromSegments(remoteDoc.noDocument.path);
8200
8493
  const version = fromDbTimestamp(remoteDoc.noDocument.readTime);
8201
- const document = MutableDocument.newNoDocument(key, version);
8202
- return remoteDoc.hasCommittedMutations
8203
- ? document.setHasCommittedMutations()
8204
- : document;
8494
+ doc = MutableDocument.newNoDocument(key, version);
8495
+ if (remoteDoc.hasCommittedMutations) {
8496
+ doc.setHasCommittedMutations();
8497
+ }
8205
8498
  }
8206
8499
  else if (remoteDoc.unknownDocument) {
8207
8500
  const key = DocumentKey.fromSegments(remoteDoc.unknownDocument.path);
8208
8501
  const version = fromDbTimestamp(remoteDoc.unknownDocument.version);
8209
- return MutableDocument.newUnknownDocument(key, version);
8502
+ doc = MutableDocument.newUnknownDocument(key, version);
8210
8503
  }
8211
8504
  else {
8212
8505
  return fail();
8213
8506
  }
8507
+ if (remoteDoc.readTime) {
8508
+ doc.setReadTime(fromDbTimestampKey(remoteDoc.readTime));
8509
+ }
8510
+ return doc;
8214
8511
  }
8215
8512
  /** Encodes a document for storage locally. */
8216
- function toDbRemoteDocument(localSerializer, document, readTime) {
8217
- const dbReadTime = toDbTimestampKey(readTime);
8513
+ function toDbRemoteDocument(localSerializer, document) {
8514
+ const dbReadTime = toDbTimestampKey(document.readTime);
8218
8515
  const parentPath = document.key.path.popLast().toArray();
8219
8516
  if (document.isFoundDocument()) {
8220
8517
  const doc = toDocument(localSerializer.remoteSerializer, document);
@@ -8225,10 +8522,10 @@ function toDbRemoteDocument(localSerializer, document, readTime) {
8225
8522
  }
8226
8523
  else if (document.isNoDocument()) {
8227
8524
  const path = document.key.path.toArray();
8228
- const readTime = toDbTimestamp(document.version);
8525
+ const version = toDbTimestamp(document.version);
8229
8526
  const hasCommittedMutations = document.hasCommittedMutations;
8230
8527
  return new DbRemoteDocument(
8231
- /* unknownDocument= */ null, new DbNoDocument(path, readTime),
8528
+ /* unknownDocument= */ null, new DbNoDocument(path, version),
8232
8529
  /* document= */ null, hasCommittedMutations, dbReadTime, parentPath);
8233
8530
  }
8234
8531
  else if (document.isUnknownDocument()) {
@@ -8309,7 +8606,7 @@ function toDbTarget(localSerializer, targetData) {
8309
8606
  const dbTimestamp = toDbTimestamp(targetData.snapshotVersion);
8310
8607
  const dbLastLimboFreeTimestamp = toDbTimestamp(targetData.lastLimboFreeSnapshotVersion);
8311
8608
  let queryProto;
8312
- if (isDocumentTarget(targetData.target)) {
8609
+ if (targetIsDocumentTarget(targetData.target)) {
8313
8610
  queryProto = toDocumentsTarget(localSerializer.remoteSerializer, targetData.target);
8314
8611
  }
8315
8612
  else {
@@ -8479,6 +8776,38 @@ class MemoryIndexManager {
8479
8776
  getCollectionParents(transaction, collectionId) {
8480
8777
  return PersistencePromise.resolve(this.collectionParentIndex.getEntries(collectionId));
8481
8778
  }
8779
+ addFieldIndex(transaction, index) {
8780
+ // Field indices are not supported with memory persistence.
8781
+ return PersistencePromise.resolve();
8782
+ }
8783
+ deleteFieldIndex(transaction, index) {
8784
+ // Field indices are not supported with memory persistence.
8785
+ return PersistencePromise.resolve();
8786
+ }
8787
+ getDocumentsMatchingTarget(transaction, fieldIndex, target) {
8788
+ // Field indices are not supported with memory persistence.
8789
+ return PersistencePromise.resolve(documentKeySet());
8790
+ }
8791
+ getFieldIndex(transaction, target) {
8792
+ // Field indices are not supported with memory persistence.
8793
+ return PersistencePromise.resolve(null);
8794
+ }
8795
+ getFieldIndexes(transaction, collectionGroup) {
8796
+ // Field indices are not supported with memory persistence.
8797
+ return PersistencePromise.resolve([]);
8798
+ }
8799
+ getNextCollectionGroupToUpdate(transaction) {
8800
+ // Field indices are not supported with memory persistence.
8801
+ return PersistencePromise.resolve(null);
8802
+ }
8803
+ updateCollectionGroup(transaction, collectionGroup, offset) {
8804
+ // Field indices are not supported with memory persistence.
8805
+ return PersistencePromise.resolve();
8806
+ }
8807
+ updateIndexEntries(transaction, documents) {
8808
+ // Field indices are not supported with memory persistence.
8809
+ return PersistencePromise.resolve();
8810
+ }
8482
8811
  }
8483
8812
  /**
8484
8813
  * Internal implementation of the collection-parent index exposed by MemoryIndexManager.
@@ -8587,6 +8916,38 @@ class IndexedDbIndexManager {
8587
8916
  return parentPaths;
8588
8917
  });
8589
8918
  }
8919
+ addFieldIndex(transaction, index) {
8920
+ // TODO(indexing): Implement
8921
+ return PersistencePromise.resolve();
8922
+ }
8923
+ deleteFieldIndex(transaction, index) {
8924
+ // TODO(indexing): Implement
8925
+ return PersistencePromise.resolve();
8926
+ }
8927
+ getDocumentsMatchingTarget(transaction, fieldIndex, target) {
8928
+ // TODO(indexing): Implement
8929
+ return PersistencePromise.resolve(documentKeySet());
8930
+ }
8931
+ getFieldIndex(transaction, target) {
8932
+ // TODO(indexing): Implement
8933
+ return PersistencePromise.resolve(null);
8934
+ }
8935
+ getFieldIndexes(transaction, collectionGroup) {
8936
+ // TODO(indexing): Implement
8937
+ return PersistencePromise.resolve([]);
8938
+ }
8939
+ getNextCollectionGroupToUpdate(transaction) {
8940
+ // TODO(indexing): Implement
8941
+ return PersistencePromise.resolve(null);
8942
+ }
8943
+ updateCollectionGroup(transaction, collectionGroup, offset) {
8944
+ // TODO(indexing): Implement
8945
+ return PersistencePromise.resolve();
8946
+ }
8947
+ updateIndexEntries(transaction, documents) {
8948
+ // TODO(indexing): Implement
8949
+ return PersistencePromise.resolve();
8950
+ }
8590
8951
  }
8591
8952
  /**
8592
8953
  * Helper to get a typed SimpleDbStore for the collectionParents
@@ -9757,7 +10118,7 @@ class IndexedDbLruDelegateImpl {
9757
10118
  // Our size accounting requires us to read all documents before
9758
10119
  // removing them.
9759
10120
  return changeBuffer.getEntry(txn, docKey).next(() => {
9760
- changeBuffer.removeEntry(docKey);
10121
+ changeBuffer.removeEntry(docKey, SnapshotVersion.min());
9761
10122
  return documentTargetStore(txn).delete(sentinelKey$1(docKey));
9762
10123
  });
9763
10124
  }
@@ -9970,27 +10331,19 @@ class ObjectMap {
9970
10331
  */
9971
10332
  class RemoteDocumentChangeBuffer {
9972
10333
  constructor() {
9973
- // A mapping of document key to the new cache entry that should be written (or null if any
9974
- // existing cache entry should be removed).
10334
+ // A mapping of document key to the new cache entry that should be written.
9975
10335
  this.changes = new ObjectMap(key => key.toString(), (l, r) => l.isEqual(r));
9976
10336
  this.changesApplied = false;
9977
10337
  }
9978
- getReadTime(key) {
9979
- const change = this.changes.get(key);
9980
- if (change) {
9981
- return change.readTime;
9982
- }
9983
- return SnapshotVersion.min();
9984
- }
9985
10338
  /**
9986
10339
  * Buffers a `RemoteDocumentCache.addEntry()` call.
9987
10340
  *
9988
10341
  * You can only modify documents that have already been retrieved via
9989
10342
  * `getEntry()/getEntries()` (enforced via IndexedDbs `apply()`).
9990
10343
  */
9991
- addEntry(document, readTime) {
10344
+ addEntry(document) {
9992
10345
  this.assertNotApplied();
9993
- this.changes.set(document.key, { document, readTime });
10346
+ this.changes.set(document.key, document);
9994
10347
  }
9995
10348
  /**
9996
10349
  * Buffers a `RemoteDocumentCache.removeEntry()` call.
@@ -9998,12 +10351,9 @@ class RemoteDocumentChangeBuffer {
9998
10351
  * You can only remove documents that have already been retrieved via
9999
10352
  * `getEntry()/getEntries()` (enforced via IndexedDbs `apply()`).
10000
10353
  */
10001
- removeEntry(key, readTime = null) {
10354
+ removeEntry(key, readTime) {
10002
10355
  this.assertNotApplied();
10003
- this.changes.set(key, {
10004
- document: MutableDocument.newInvalidDocument(key),
10005
- readTime
10006
- });
10356
+ this.changes.set(key, MutableDocument.newInvalidDocument(key).setReadTime(readTime));
10007
10357
  }
10008
10358
  /**
10009
10359
  * Looks up an entry in the cache. The buffered changes will first be checked,
@@ -10020,7 +10370,7 @@ class RemoteDocumentChangeBuffer {
10020
10370
  this.assertNotApplied();
10021
10371
  const bufferedEntry = this.changes.get(documentKey);
10022
10372
  if (bufferedEntry !== undefined) {
10023
- return PersistencePromise.resolve(bufferedEntry.document);
10373
+ return PersistencePromise.resolve(bufferedEntry);
10024
10374
  }
10025
10375
  else {
10026
10376
  return this.getFromCache(transaction, documentKey);
@@ -10231,7 +10581,7 @@ class IndexedDbRemoteDocumentCacheImpl {
10231
10581
  if (key.length !== immediateChildrenPathLength) {
10232
10582
  return;
10233
10583
  }
10234
- const document = fromDbRemoteDocument(this.serializer, dbRemoteDoc);
10584
+ const document = this.maybeDecodeDocument(DocumentKey.fromSegments(key), dbRemoteDoc);
10235
10585
  if (!query.path.isPrefixOf(document.key.path)) {
10236
10586
  control.done();
10237
10587
  }
@@ -10259,8 +10609,8 @@ class IndexedDbRemoteDocumentCacheImpl {
10259
10609
  return documentGlobalStore(txn).put(DbRemoteDocumentGlobal.key, metadata);
10260
10610
  }
10261
10611
  /**
10262
- * Decodes `remoteDoc` and returns the document (or null, if the document
10263
- * corresponds to the format used for sentinel deletes).
10612
+ * Decodes `dbRemoteDoc` and returns the document (or an invalid document if
10613
+ * the document corresponds to the format used for sentinel deletes).
10264
10614
  */
10265
10615
  maybeDecodeDocument(documentKey, dbRemoteDoc) {
10266
10616
  if (dbRemoteDoc) {
@@ -10354,8 +10704,8 @@ class IndexedDbRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
10354
10704
  let collectionParents = new SortedSet((l, r) => primitiveComparator(l.canonicalString(), r.canonicalString()));
10355
10705
  this.changes.forEach((key, documentChange) => {
10356
10706
  const previousSize = this.documentSizes.get(key);
10357
- if (documentChange.document.isValidDocument()) {
10358
- const doc = toDbRemoteDocument(this.documentCache.serializer, documentChange.document, this.getReadTime(key));
10707
+ if (documentChange.isValidDocument()) {
10708
+ const doc = toDbRemoteDocument(this.documentCache.serializer, documentChange);
10359
10709
  collectionParents = collectionParents.add(key.path.popLast());
10360
10710
  const size = dbDocumentSize(doc);
10361
10711
  sizeDelta += size - previousSize;
@@ -10368,7 +10718,7 @@ class IndexedDbRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
10368
10718
  // RemoteDocumentCache. This entry is represented by a NoDocument
10369
10719
  // with a version of 0 and ignored by `maybeDecodeDocument()` but
10370
10720
  // preserved in `getNewDocumentChanges()`.
10371
- const deletedDoc = toDbRemoteDocument(this.documentCache.serializer, MutableDocument.newNoDocument(key, SnapshotVersion.min()), this.getReadTime(key));
10721
+ const deletedDoc = toDbRemoteDocument(this.documentCache.serializer, documentChange.convertToNoDocument(SnapshotVersion.min()));
10372
10722
  promises.push(this.documentCache.addEntry(transaction, key, deletedDoc));
10373
10723
  }
10374
10724
  else {
@@ -10449,9 +10799,6 @@ class SchemaConverter {
10449
10799
  * and local feature development.
10450
10800
  */
10451
10801
  createOrUpgrade(db, txn, fromVersion, toVersion) {
10452
- hardAssert(fromVersion < toVersion &&
10453
- fromVersion >= 0 &&
10454
- toVersion <= SCHEMA_VERSION);
10455
10802
  const simpleDbTransaction = new SimpleDbTransaction('createOrUpgrade', txn);
10456
10803
  if (fromVersion < 1 && toVersion >= 1) {
10457
10804
  createPrimaryClientStore(db);
@@ -10518,6 +10865,11 @@ class SchemaConverter {
10518
10865
  createNamedQueriesStore(db);
10519
10866
  });
10520
10867
  }
10868
+ if (fromVersion < 12 && toVersion >= 12) {
10869
+ p = p.next(() => {
10870
+ createFieldIndex(db);
10871
+ });
10872
+ }
10521
10873
  return p;
10522
10874
  }
10523
10875
  addDocumentGlobal(txn) {
@@ -10724,6 +11076,17 @@ function createNamedQueriesStore(db) {
10724
11076
  db.createObjectStore(DbNamedQuery.store, {
10725
11077
  keyPath: DbNamedQuery.keyPath
10726
11078
  });
11079
+ }
11080
+ function createFieldIndex(db) {
11081
+ db.createObjectStore(DbIndexConfiguration.store, {
11082
+ keyPath: DbIndexConfiguration.keyPath
11083
+ });
11084
+ db.createObjectStore(DbIndexState.store, {
11085
+ keyPath: DbIndexState.keyPath
11086
+ });
11087
+ db.createObjectStore(DbIndexEntries.store, {
11088
+ keyPath: DbIndexEntries.keyPath
11089
+ });
10727
11090
  }
10728
11091
 
10729
11092
  /**
@@ -11955,14 +12318,14 @@ function localStoreApplyRemoteEventToLocalCache(localStore, remoteEvent) {
11955
12318
  }
11956
12319
  });
11957
12320
  let changedDocs = mutableDocumentMap();
11958
- remoteEvent.documentUpdates.forEach((key, doc) => {
12321
+ remoteEvent.documentUpdates.forEach(key => {
11959
12322
  if (remoteEvent.resolvedLimboDocuments.has(key)) {
11960
12323
  promises.push(localStoreImpl.persistence.referenceDelegate.updateLimboDocument(txn, key));
11961
12324
  }
11962
12325
  });
11963
12326
  // Each loop iteration only affects its "own" doc, so it's safe to get all the remote
11964
12327
  // documents in advance in a single call.
11965
- promises.push(populateDocumentChangeBuffer(txn, documentBuffer, remoteEvent.documentUpdates, remoteVersion, undefined).next(result => {
12328
+ promises.push(populateDocumentChangeBuffer(txn, documentBuffer, remoteEvent.documentUpdates).next(result => {
11966
12329
  changedDocs = result;
11967
12330
  }));
11968
12331
  // HACK: The only reason we allow a null snapshot version is so that we
@@ -12003,17 +12366,13 @@ function localStoreApplyRemoteEventToLocalCache(localStore, remoteEvent) {
12003
12366
  * Note: this function will use `documentVersions` if it is defined;
12004
12367
  * when it is not defined, resorts to `globalVersion`.
12005
12368
  */
12006
- function populateDocumentChangeBuffer(txn, documentBuffer, documents, globalVersion,
12007
- // TODO(wuandy): We could add `readTime` to MaybeDocument instead to remove
12008
- // this parameter.
12009
- documentVersions) {
12369
+ function populateDocumentChangeBuffer(txn, documentBuffer, documents) {
12010
12370
  let updatedKeys = documentKeySet();
12011
12371
  documents.forEach(k => (updatedKeys = updatedKeys.add(k)));
12012
12372
  return documentBuffer.getEntries(txn, updatedKeys).next(existingDocs => {
12013
12373
  let changedDocs = mutableDocumentMap();
12014
12374
  documents.forEach((key, doc) => {
12015
12375
  const existingDoc = existingDocs.get(key);
12016
- const docReadTime = (documentVersions === null || documentVersions === void 0 ? void 0 : documentVersions.get(key)) || globalVersion;
12017
12376
  // Note: The order of the steps below is important, since we want
12018
12377
  // to ensure that rejected limbo resolutions (which fabricate
12019
12378
  // NoDocuments with SnapshotVersion.min()) never add documents to
@@ -12022,14 +12381,14 @@ documentVersions) {
12022
12381
  // NoDocuments with SnapshotVersion.min() are used in manufactured
12023
12382
  // events. We remove these documents from cache since we lost
12024
12383
  // access.
12025
- documentBuffer.removeEntry(key, docReadTime);
12384
+ documentBuffer.removeEntry(key, doc.readTime);
12026
12385
  changedDocs = changedDocs.insert(key, doc);
12027
12386
  }
12028
12387
  else if (!existingDoc.isValidDocument() ||
12029
12388
  doc.version.compareTo(existingDoc.version) > 0 ||
12030
12389
  (doc.version.compareTo(existingDoc.version) === 0 &&
12031
12390
  existingDoc.hasPendingWrites)) {
12032
- documentBuffer.addEntry(doc, docReadTime);
12391
+ documentBuffer.addEntry(doc);
12033
12392
  changedDocs = changedDocs.insert(key, doc);
12034
12393
  }
12035
12394
  else {
@@ -12283,7 +12642,8 @@ function applyWriteToRemoteDocuments(localStoreImpl, txn, batchResult, documentB
12283
12642
  // We use the commitVersion as the readTime rather than the
12284
12643
  // document's updateTime since the updateTime is not advanced
12285
12644
  // for updates that do not modify the underlying document.
12286
- documentBuffer.addEntry(doc, batchResult.commitVersion);
12645
+ doc.setReadTime(batchResult.commitVersion);
12646
+ documentBuffer.addEntry(doc);
12287
12647
  }
12288
12648
  }
12289
12649
  });
@@ -12384,14 +12744,14 @@ async function localStoreApplyBundledDocuments(localStore, bundleConverter, docu
12384
12744
  const localStoreImpl = debugCast(localStore);
12385
12745
  let documentKeys = documentKeySet();
12386
12746
  let documentMap = mutableDocumentMap();
12387
- let versionMap = documentVersionMap();
12388
12747
  for (const bundleDoc of documents) {
12389
12748
  const documentKey = bundleConverter.toDocumentKey(bundleDoc.metadata.name);
12390
12749
  if (bundleDoc.document) {
12391
12750
  documentKeys = documentKeys.add(documentKey);
12392
12751
  }
12393
- documentMap = documentMap.insert(documentKey, bundleConverter.toMutableDocument(bundleDoc));
12394
- versionMap = versionMap.insert(documentKey, bundleConverter.toSnapshotVersion(bundleDoc.metadata.readTime));
12752
+ const doc = bundleConverter.toMutableDocument(bundleDoc);
12753
+ doc.setReadTime(bundleConverter.toSnapshotVersion(bundleDoc.metadata.readTime));
12754
+ documentMap = documentMap.insert(documentKey, doc);
12395
12755
  }
12396
12756
  const documentBuffer = localStoreImpl.remoteDocuments.newChangeBuffer({
12397
12757
  trackRemovals: true // Make sure document removals show up in `getNewDocumentChanges()`
@@ -12400,7 +12760,7 @@ async function localStoreApplyBundledDocuments(localStore, bundleConverter, docu
12400
12760
  // they will not get garbage collected right away.
12401
12761
  const umbrellaTargetData = await localStoreAllocateTarget(localStoreImpl, umbrellaTarget(bundleName));
12402
12762
  return localStoreImpl.persistence.runTransaction('Apply bundle documents', 'readwrite', txn => {
12403
- return populateDocumentChangeBuffer(txn, documentBuffer, documentMap, SnapshotVersion.min(), versionMap)
12763
+ return populateDocumentChangeBuffer(txn, documentBuffer, documentMap)
12404
12764
  .next(changedDocs => {
12405
12765
  documentBuffer.apply(txn);
12406
12766
  return changedDocs;
@@ -12881,15 +13241,14 @@ class MemoryRemoteDocumentCacheImpl {
12881
13241
  * All calls of `addEntry` are required to go through the RemoteDocumentChangeBuffer
12882
13242
  * returned by `newChangeBuffer()`.
12883
13243
  */
12884
- addEntry(transaction, doc, readTime) {
13244
+ addEntry(transaction, doc) {
12885
13245
  const key = doc.key;
12886
13246
  const entry = this.docs.get(key);
12887
13247
  const previousSize = entry ? entry.size : 0;
12888
13248
  const currentSize = this.sizer(doc);
12889
13249
  this.docs = this.docs.insert(key, {
12890
13250
  document: doc.mutableCopy(),
12891
- size: currentSize,
12892
- readTime
13251
+ size: currentSize
12893
13252
  });
12894
13253
  this.size += currentSize - previousSize;
12895
13254
  return this.indexManager.addToCollectionParentIndex(transaction, key.path.popLast());
@@ -12930,11 +13289,11 @@ class MemoryRemoteDocumentCacheImpl {
12930
13289
  const prefix = new DocumentKey(query.path.child(''));
12931
13290
  const iterator = this.docs.getIteratorFrom(prefix);
12932
13291
  while (iterator.hasNext()) {
12933
- const { key, value: { document, readTime } } = iterator.getNext();
13292
+ const { key, value: { document } } = iterator.getNext();
12934
13293
  if (!query.path.isPrefixOf(key.path)) {
12935
13294
  break;
12936
13295
  }
12937
- if (readTime.compareTo(sinceReadTime) <= 0) {
13296
+ if (document.readTime.compareTo(sinceReadTime) <= 0) {
12938
13297
  continue;
12939
13298
  }
12940
13299
  if (!queryMatches(query, document)) {
@@ -12978,8 +13337,8 @@ class MemoryRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
12978
13337
  applyChanges(transaction) {
12979
13338
  const promises = [];
12980
13339
  this.changes.forEach((key, doc) => {
12981
- if (doc.document.isValidDocument()) {
12982
- promises.push(this.documentCache.addEntry(transaction, doc.document, this.getReadTime(key)));
13340
+ if (doc.isValidDocument()) {
13341
+ promises.push(this.documentCache.addEntry(transaction, doc));
12983
13342
  }
12984
13343
  else {
12985
13344
  this.documentCache.removeEntry(key);
@@ -13292,7 +13651,7 @@ class MemoryEagerDelegate {
13292
13651
  const key = DocumentKey.fromPath(path);
13293
13652
  return this.isReferenced(txn, key).next(isReferenced => {
13294
13653
  if (!isReferenced) {
13295
- changeBuffer.removeEntry(key);
13654
+ changeBuffer.removeEntry(key, SnapshotVersion.min());
13296
13655
  }
13297
13656
  });
13298
13657
  }).next(() => {
@@ -17072,6 +17431,40 @@ const nested = {
17072
17431
  id: 2
17073
17432
  }
17074
17433
  }
17434
+ },
17435
+ methodSignature: {
17436
+ rule: "repeated",
17437
+ type: "string",
17438
+ id: 1051,
17439
+ extend: "google.protobuf.MethodOptions"
17440
+ },
17441
+ defaultHost: {
17442
+ type: "string",
17443
+ id: 1049,
17444
+ extend: "google.protobuf.ServiceOptions"
17445
+ },
17446
+ oauthScopes: {
17447
+ type: "string",
17448
+ id: 1050,
17449
+ extend: "google.protobuf.ServiceOptions"
17450
+ },
17451
+ fieldBehavior: {
17452
+ rule: "repeated",
17453
+ type: "google.api.FieldBehavior",
17454
+ id: 1052,
17455
+ extend: "google.protobuf.FieldOptions"
17456
+ },
17457
+ FieldBehavior: {
17458
+ values: {
17459
+ FIELD_BEHAVIOR_UNSPECIFIED: 0,
17460
+ OPTIONAL: 1,
17461
+ REQUIRED: 2,
17462
+ OUTPUT_ONLY: 3,
17463
+ INPUT_ONLY: 4,
17464
+ IMMUTABLE: 5,
17465
+ UNORDERED_LIST: 6,
17466
+ NON_EMPTY_DEFAULT: 7
17467
+ }
17075
17468
  }
17076
17469
  }
17077
17470
  },
@@ -20315,6 +20708,9 @@ async function syncEngineRejectListen(syncEngine, targetId, err) {
20315
20708
  // store to purge a document. However, it would be tricky to keep all of
20316
20709
  // the local store's invariants with another method.
20317
20710
  let documentUpdates = new SortedMap(DocumentKey.comparator);
20711
+ // TODO(b/217189216): This limbo document should ideally have a read time,
20712
+ // so that it is picked up by any read-time based scans. The backend,
20713
+ // however, does not send a read time for target removals.
20318
20714
  documentUpdates = documentUpdates.insert(limboKey, MutableDocument.newNoDocument(limboKey, SnapshotVersion.min()));
20319
20715
  const resolvedLimboDocuments = documentKeySet().add(limboKey);
20320
20716
  const event = new RemoteEvent(SnapshotVersion.min(),
@@ -21882,13 +22278,16 @@ class FirestoreClient {
21882
22278
  this.user = User.UNAUTHENTICATED;
21883
22279
  this.clientId = AutoId.newId();
21884
22280
  this.authCredentialListener = () => Promise.resolve();
22281
+ this.appCheckCredentialListener = () => Promise.resolve();
21885
22282
  this.authCredentials.start(asyncQueue, async (user) => {
21886
22283
  logDebug(LOG_TAG$2, 'Received user=', user.uid);
21887
22284
  await this.authCredentialListener(user);
21888
22285
  this.user = user;
21889
22286
  });
21890
- // Register an empty credentials change listener to activate token refresh.
21891
- this.appCheckCredentials.start(asyncQueue, () => Promise.resolve());
22287
+ this.appCheckCredentials.start(asyncQueue, newAppCheckToken => {
22288
+ logDebug(LOG_TAG$2, 'Received new app check token=', newAppCheckToken);
22289
+ return this.appCheckCredentialListener(newAppCheckToken, this.user);
22290
+ });
21892
22291
  }
21893
22292
  async getConfiguration() {
21894
22293
  return {
@@ -21904,6 +22303,9 @@ class FirestoreClient {
21904
22303
  setCredentialChangeListener(listener) {
21905
22304
  this.authCredentialListener = listener;
21906
22305
  }
22306
+ setAppCheckTokenChangeListener(listener) {
22307
+ this.appCheckCredentialListener = listener;
22308
+ }
21907
22309
  /**
21908
22310
  * Checks that the client has not been terminated. Ensures that other methods on
21909
22311
  * this class cannot be called after the client is terminated.
@@ -21965,6 +22367,7 @@ async function setOnlineComponentProvider(client, onlineComponentProvider) {
21965
22367
  // The CredentialChangeListener of the online component provider takes
21966
22368
  // precedence over the offline component provider.
21967
22369
  client.setCredentialChangeListener(user => remoteStoreHandleCredentialChange(onlineComponentProvider.remoteStore, user));
22370
+ client.setAppCheckTokenChangeListener((_, user) => remoteStoreHandleCredentialChange(onlineComponentProvider.remoteStore, user));
21968
22371
  client.onlineComponents = onlineComponentProvider;
21969
22372
  }
21970
22373
  async function ensureOfflineComponents(client) {
@@ -22252,72 +22655,6 @@ function createBundleReader(data, serializer) {
22252
22655
  return newBundleReader(toByteStreamReader(content), serializer);
22253
22656
  }
22254
22657
 
22255
- /**
22256
- * @license
22257
- * Copyright 2017 Google LLC
22258
- *
22259
- * Licensed under the Apache License, Version 2.0 (the "License");
22260
- * you may not use this file except in compliance with the License.
22261
- * You may obtain a copy of the License at
22262
- *
22263
- * http://www.apache.org/licenses/LICENSE-2.0
22264
- *
22265
- * Unless required by applicable law or agreed to in writing, software
22266
- * distributed under the License is distributed on an "AS IS" BASIS,
22267
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22268
- * See the License for the specific language governing permissions and
22269
- * limitations under the License.
22270
- */
22271
- class DatabaseInfo {
22272
- /**
22273
- * Constructs a DatabaseInfo using the provided host, databaseId and
22274
- * persistenceKey.
22275
- *
22276
- * @param databaseId - The database to use.
22277
- * @param appId - The Firebase App Id.
22278
- * @param persistenceKey - A unique identifier for this Firestore's local
22279
- * storage (used in conjunction with the databaseId).
22280
- * @param host - The Firestore backend host to connect to.
22281
- * @param ssl - Whether to use SSL when connecting.
22282
- * @param forceLongPolling - Whether to use the forceLongPolling option
22283
- * when using WebChannel as the network transport.
22284
- * @param autoDetectLongPolling - Whether to use the detectBufferingProxy
22285
- * option when using WebChannel as the network transport.
22286
- * @param useFetchStreams Whether to use the Fetch API instead of
22287
- * XMLHTTPRequest
22288
- */
22289
- constructor(databaseId, appId, persistenceKey, host, ssl, forceLongPolling, autoDetectLongPolling, useFetchStreams) {
22290
- this.databaseId = databaseId;
22291
- this.appId = appId;
22292
- this.persistenceKey = persistenceKey;
22293
- this.host = host;
22294
- this.ssl = ssl;
22295
- this.forceLongPolling = forceLongPolling;
22296
- this.autoDetectLongPolling = autoDetectLongPolling;
22297
- this.useFetchStreams = useFetchStreams;
22298
- }
22299
- }
22300
- /** The default database name for a project. */
22301
- const DEFAULT_DATABASE_NAME = '(default)';
22302
- /**
22303
- * Represents the database ID a Firestore client is associated with.
22304
- * @internal
22305
- */
22306
- class DatabaseId {
22307
- constructor(projectId, database) {
22308
- this.projectId = projectId;
22309
- this.database = database ? database : DEFAULT_DATABASE_NAME;
22310
- }
22311
- get isDefaultDatabase() {
22312
- return this.database === DEFAULT_DATABASE_NAME;
22313
- }
22314
- isEqual(other) {
22315
- return (other instanceof DatabaseId &&
22316
- other.projectId === this.projectId &&
22317
- other.database === this.database);
22318
- }
22319
- }
22320
-
22321
22658
  /**
22322
22659
  * @license
22323
22660
  * Copyright 2020 Google LLC
@@ -23517,13 +23854,13 @@ function terminate(firestore) {
23517
23854
  /**
23518
23855
  * Loads a Firestore bundle into the local cache.
23519
23856
  *
23520
- * @param firestore - The {@link Firestore} instance to load bundles for for.
23521
- * @param bundleData - An object representing the bundle to be loaded. Valid objects are
23522
- * `ArrayBuffer`, `ReadableStream<Uint8Array>` or `string`.
23857
+ * @param firestore - The {@link Firestore} instance to load bundles for.
23858
+ * @param bundleData - An object representing the bundle to be loaded. Valid
23859
+ * objects are `ArrayBuffer`, `ReadableStream<Uint8Array>` or `string`.
23523
23860
  *
23524
- * @returns
23525
- * A `LoadBundleTask` object, which notifies callers with progress updates, and completion
23526
- * or error events. It can be used as a `Promise<LoadBundleTaskProgress>`.
23861
+ * @returns A `LoadBundleTask` object, which notifies callers with progress
23862
+ * updates, and completion or error events. It can be used as a
23863
+ * `Promise<LoadBundleTaskProgress>`.
23527
23864
  */
23528
23865
  function loadBundle(firestore, bundleData) {
23529
23866
  firestore = cast(firestore, Firestore);
@@ -23533,11 +23870,16 @@ function loadBundle(firestore, bundleData) {
23533
23870
  return resultTask;
23534
23871
  }
23535
23872
  /**
23536
- * Reads a Firestore {@link Query} from local cache, identified by the given name.
23873
+ * Reads a Firestore {@link Query} from local cache, identified by the given
23874
+ * name.
23537
23875
  *
23538
23876
  * The named queries are packaged into bundles on the server side (along
23539
- * with resulting documents), and loaded to local cache using `loadBundle`. Once in local
23540
- * cache, use this method to extract a {@link Query} by name.
23877
+ * with resulting documents), and loaded to local cache using `loadBundle`. Once
23878
+ * in local cache, use this method to extract a {@link Query} by name.
23879
+ *
23880
+ * @param firestore - The {@link Firestore} instance to read the query from.
23881
+ * @param name - The name of the query.
23882
+ * @returns A `Promise` that is resolved with the Query or `null`.
23541
23883
  */
23542
23884
  function namedQuery(firestore, name) {
23543
23885
  firestore = cast(firestore, Firestore);
@@ -24686,8 +25028,7 @@ class DocumentSnapshot extends DocumentSnapshot$1 {
24686
25028
  this.metadata = metadata;
24687
25029
  }
24688
25030
  /**
24689
- * Property of the `DocumentSnapshot` that signals whether or not the data
24690
- * exists. True if the document exists.
25031
+ * Returns whether or not the data exists. True if the document exists.
24691
25032
  */
24692
25033
  exists() {
24693
25034
  return super.exists();
@@ -25061,51 +25402,53 @@ function limitToLast(limit) {
25061
25402
  return new QueryLimitConstraint('limitToLast', limit, "L" /* Last */);
25062
25403
  }
25063
25404
  class QueryStartAtConstraint extends QueryConstraint {
25064
- constructor(type, _docOrFields, _before) {
25405
+ constructor(type, _docOrFields, _inclusive) {
25065
25406
  super();
25066
25407
  this.type = type;
25067
25408
  this._docOrFields = _docOrFields;
25068
- this._before = _before;
25409
+ this._inclusive = _inclusive;
25069
25410
  }
25070
25411
  _apply(query) {
25071
- const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._before);
25412
+ const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
25072
25413
  return new Query(query.firestore, query.converter, queryWithStartAt(query._query, bound));
25073
25414
  }
25074
25415
  }
25075
25416
  function startAt(...docOrFields) {
25076
- return new QueryStartAtConstraint('startAt', docOrFields, /*before=*/ true);
25417
+ return new QueryStartAtConstraint('startAt', docOrFields,
25418
+ /*inclusive=*/ true);
25077
25419
  }
25078
25420
  function startAfter(...docOrFields) {
25079
25421
  return new QueryStartAtConstraint('startAfter', docOrFields,
25080
- /*before=*/ false);
25422
+ /*inclusive=*/ false);
25081
25423
  }
25082
25424
  class QueryEndAtConstraint extends QueryConstraint {
25083
- constructor(type, _docOrFields, _before) {
25425
+ constructor(type, _docOrFields, _inclusive) {
25084
25426
  super();
25085
25427
  this.type = type;
25086
25428
  this._docOrFields = _docOrFields;
25087
- this._before = _before;
25429
+ this._inclusive = _inclusive;
25088
25430
  }
25089
25431
  _apply(query) {
25090
- const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._before);
25432
+ const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
25091
25433
  return new Query(query.firestore, query.converter, queryWithEndAt(query._query, bound));
25092
25434
  }
25093
25435
  }
25094
25436
  function endBefore(...docOrFields) {
25095
- return new QueryEndAtConstraint('endBefore', docOrFields, /*before=*/ true);
25437
+ return new QueryEndAtConstraint('endBefore', docOrFields,
25438
+ /*inclusive=*/ false);
25096
25439
  }
25097
25440
  function endAt(...docOrFields) {
25098
- return new QueryEndAtConstraint('endAt', docOrFields, /*before=*/ false);
25441
+ return new QueryEndAtConstraint('endAt', docOrFields, /*inclusive=*/ true);
25099
25442
  }
25100
25443
  /** Helper function to create a bound from a document or fields */
25101
- function newQueryBoundFromDocOrFields(query, methodName, docOrFields, before) {
25444
+ function newQueryBoundFromDocOrFields(query, methodName, docOrFields, inclusive) {
25102
25445
  docOrFields[0] = util$1.getModularInstance(docOrFields[0]);
25103
25446
  if (docOrFields[0] instanceof DocumentSnapshot$1) {
25104
- return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, before);
25447
+ return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, inclusive);
25105
25448
  }
25106
25449
  else {
25107
25450
  const reader = newUserDataReader(query.firestore);
25108
- return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, before);
25451
+ return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, inclusive);
25109
25452
  }
25110
25453
  }
25111
25454
  function newQueryFilter(query, methodName, dataReader, databaseId, fieldPath, op, value) {
@@ -25163,7 +25506,7 @@ function newQueryOrderBy(query, fieldPath, direction) {
25163
25506
  * of the query or if any of the fields in the order by are an uncommitted
25164
25507
  * server timestamp.
25165
25508
  */
25166
- function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
25509
+ function newQueryBoundFromDocument(query, databaseId, methodName, doc, inclusive) {
25167
25510
  if (!doc) {
25168
25511
  throw new FirestoreError(Code.NOT_FOUND, `Can't use a DocumentSnapshot that doesn't exist for ` +
25169
25512
  `${methodName}().`);
@@ -25200,12 +25543,12 @@ function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
25200
25543
  }
25201
25544
  }
25202
25545
  }
25203
- return new Bound(components, before);
25546
+ return new Bound(components, inclusive);
25204
25547
  }
25205
25548
  /**
25206
25549
  * Converts a list of field values to a `Bound` for the given query.
25207
25550
  */
25208
- function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, before) {
25551
+ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, inclusive) {
25209
25552
  // Use explicit order by's because it has to match the query the user made
25210
25553
  const orderBy = query.explicitOrderBy;
25211
25554
  if (values.length > orderBy.length) {
@@ -25242,7 +25585,7 @@ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, valu
25242
25585
  components.push(wrapped);
25243
25586
  }
25244
25587
  }
25245
- return new Bound(components, before);
25588
+ return new Bound(components, inclusive);
25246
25589
  }
25247
25590
  /**
25248
25591
  * Parses the given `documentIdValue` into a `ReferenceValue`, throwing
@@ -26227,6 +26570,71 @@ function writeBatch(firestore) {
26227
26570
  return new WriteBatch(firestore, mutations => executeWrite(firestore, mutations));
26228
26571
  }
26229
26572
 
26573
+ /**
26574
+ * @license
26575
+ * Copyright 2021 Google LLC
26576
+ *
26577
+ * Licensed under the Apache License, Version 2.0 (the "License");
26578
+ * you may not use this file except in compliance with the License.
26579
+ * You may obtain a copy of the License at
26580
+ *
26581
+ * http://www.apache.org/licenses/LICENSE-2.0
26582
+ *
26583
+ * Unless required by applicable law or agreed to in writing, software
26584
+ * distributed under the License is distributed on an "AS IS" BASIS,
26585
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26586
+ * See the License for the specific language governing permissions and
26587
+ * limitations under the License.
26588
+ */
26589
+ function setIndexConfiguration(firestore, jsonOrConfiguration) {
26590
+ firestore = cast(firestore, Firestore);
26591
+ ensureFirestoreConfigured(firestore);
26592
+ const indexConfiguration = typeof jsonOrConfiguration === 'string'
26593
+ ? tryParseJson(jsonOrConfiguration)
26594
+ : jsonOrConfiguration;
26595
+ const parsedIndexes = [];
26596
+ // PORTING NOTE: We don't return an error if the user has not enabled
26597
+ // persistence since `enableIndexeddbPersistence()` can fail on the Web.
26598
+ if (Array.isArray(indexConfiguration.indexes)) {
26599
+ for (const index of indexConfiguration.indexes) {
26600
+ const collectionGroup = tryGetString(index, 'collectionGroup');
26601
+ const segments = [];
26602
+ if (Array.isArray(index.fields)) {
26603
+ for (const field of index.fields) {
26604
+ const fieldPathString = tryGetString(field, 'fieldPath');
26605
+ const fieldPath = fieldPathFromDotSeparatedString('setIndexConfiguration', fieldPathString);
26606
+ if (field.arrayConfig === 'CONTAINS') {
26607
+ segments.push(new IndexSegment(fieldPath, 2 /* CONTAINS */));
26608
+ }
26609
+ else if (field.order === 'ASCENDING') {
26610
+ segments.push(new IndexSegment(fieldPath, 0 /* ASCENDING */));
26611
+ }
26612
+ else if (field.order === 'DESCENDING') {
26613
+ segments.push(new IndexSegment(fieldPath, 1 /* DESCENDING */));
26614
+ }
26615
+ }
26616
+ }
26617
+ parsedIndexes.push(new FieldIndex(FieldIndex.UNKNOWN_ID, collectionGroup, segments, IndexState.empty()));
26618
+ }
26619
+ }
26620
+ // TODO(indexing): Configure indexes
26621
+ return Promise.resolve();
26622
+ }
26623
+ function tryParseJson(json) {
26624
+ try {
26625
+ return JSON.parse(json);
26626
+ }
26627
+ catch (e) {
26628
+ throw new FirestoreError(Code.INVALID_ARGUMENT, 'Failed to parse JSON:' + e.message);
26629
+ }
26630
+ }
26631
+ function tryGetString(data, property) {
26632
+ if (typeof data[property] !== 'string') {
26633
+ throw new FirestoreError(Code.INVALID_ARGUMENT, 'Missing string value for: ' + property);
26634
+ }
26635
+ return data[property];
26636
+ }
26637
+
26230
26638
  /**
26231
26639
  * @license
26232
26640
  * Copyright 2021 Google LLC
@@ -26274,6 +26682,7 @@ exports._cast = cast;
26274
26682
  exports._debugAssert = debugAssert;
26275
26683
  exports._isBase64Available = isBase64Available;
26276
26684
  exports._logWarn = logWarn;
26685
+ exports._setIndexConfiguration = setIndexConfiguration;
26277
26686
  exports._validateIsNotUsedTogether = validateIsNotUsedTogether;
26278
26687
  exports.addDoc = addDoc;
26279
26688
  exports.arrayRemove = arrayRemove;