@firebase/firestore 3.4.4-canary.222f264ff → 3.4.4-canary.6c8eabfc5

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 (112) hide show
  1. package/dist/firestore/src/api/{query.d.ts → filter.d.ts} +0 -0
  2. package/dist/firestore/src/api/snapshot.d.ts +1 -2
  3. package/dist/firestore/src/api.d.ts +1 -1
  4. package/dist/firestore/src/core/database_info.d.ts +1 -0
  5. package/dist/firestore/src/core/target.d.ts +34 -5
  6. package/dist/firestore/src/lite-api/query.d.ts +2 -2
  7. package/dist/firestore/src/local/index_manager.d.ts +52 -0
  8. package/dist/firestore/src/local/indexeddb_index_manager.d.ts +11 -0
  9. package/dist/firestore/src/local/indexeddb_schema.d.ts +121 -7
  10. package/dist/firestore/src/local/local_serializer.d.ts +1 -1
  11. package/dist/firestore/src/local/memory_index_manager.d.ts +11 -0
  12. package/dist/firestore/src/local/remote_document_change_buffer.d.ts +3 -12
  13. package/dist/firestore/src/local/simple_db.d.ts +1 -0
  14. package/dist/firestore/src/model/document.d.ts +7 -0
  15. package/dist/firestore/src/model/document_key.d.ts +1 -0
  16. package/dist/firestore/src/model/field_index.d.ts +87 -7
  17. package/dist/firestore/src/model/values.d.ts +7 -0
  18. package/dist/firestore/test/unit/local/test_remote_document_cache.d.ts +1 -1
  19. package/dist/firestore/test/unit/model/field_index.test.d.ts +17 -0
  20. package/dist/firestore/test/unit/model/target.test.d.ts +17 -0
  21. package/dist/firestore/test/util/helpers.d.ts +8 -2
  22. package/dist/index.d.ts +1 -2
  23. package/dist/index.esm2017.js +3451 -3194
  24. package/dist/index.esm2017.js.map +1 -1
  25. package/dist/index.esm5.js +3430 -3264
  26. package/dist/index.esm5.js.map +1 -1
  27. package/dist/index.node.cjs.js +543 -242
  28. package/dist/index.node.cjs.js.map +1 -1
  29. package/dist/index.node.mjs +543 -242
  30. package/dist/index.node.mjs.map +1 -1
  31. package/dist/index.rn.js +3520 -3301
  32. package/dist/index.rn.js.map +1 -1
  33. package/dist/internal.d.ts +183 -16
  34. package/dist/lite/firestore/src/api/{query.d.ts → filter.d.ts} +0 -0
  35. package/dist/lite/firestore/src/api/snapshot.d.ts +1 -2
  36. package/dist/lite/firestore/src/api.d.ts +1 -1
  37. package/dist/lite/firestore/src/core/database_info.d.ts +1 -0
  38. package/dist/lite/firestore/src/core/target.d.ts +34 -5
  39. package/dist/lite/firestore/src/lite-api/query.d.ts +2 -2
  40. package/dist/lite/firestore/src/local/index_manager.d.ts +52 -0
  41. package/dist/lite/firestore/src/local/indexeddb_index_manager.d.ts +11 -0
  42. package/dist/lite/firestore/src/local/indexeddb_schema.d.ts +121 -7
  43. package/dist/lite/firestore/src/local/local_serializer.d.ts +1 -1
  44. package/dist/lite/firestore/src/local/memory_index_manager.d.ts +11 -0
  45. package/dist/lite/firestore/src/local/remote_document_change_buffer.d.ts +3 -12
  46. package/dist/lite/firestore/src/local/simple_db.d.ts +1 -0
  47. package/dist/lite/firestore/src/model/document.d.ts +7 -0
  48. package/dist/lite/firestore/src/model/document_key.d.ts +1 -0
  49. package/dist/lite/firestore/src/model/field_index.d.ts +87 -7
  50. package/dist/lite/firestore/src/model/values.d.ts +7 -0
  51. package/dist/lite/firestore/test/unit/local/test_remote_document_cache.d.ts +1 -1
  52. package/dist/lite/firestore/test/unit/model/field_index.test.d.ts +17 -0
  53. package/dist/lite/firestore/test/unit/model/target.test.d.ts +17 -0
  54. package/dist/lite/firestore/test/util/helpers.d.ts +8 -2
  55. package/dist/lite/index.browser.esm2017.js +1166 -1152
  56. package/dist/lite/index.browser.esm2017.js.map +1 -1
  57. package/dist/lite/index.browser.esm5.js +367 -359
  58. package/dist/lite/index.browser.esm5.js.map +1 -1
  59. package/dist/lite/index.node.cjs.js +53 -34
  60. package/dist/lite/index.node.cjs.js.map +1 -1
  61. package/dist/lite/index.node.mjs +53 -34
  62. package/dist/lite/index.node.mjs.map +1 -1
  63. package/dist/lite/index.rn.esm2017.js +318 -304
  64. package/dist/lite/index.rn.esm2017.js.map +1 -1
  65. package/dist/lite/internal.d.ts +11 -2
  66. package/dist/lite/packages/firestore/dist/lite/index.browser.esm2017.d.ts +125 -124
  67. package/dist/lite/packages/firestore/src/api/{query.d.ts → filter.d.ts} +0 -0
  68. package/dist/lite/packages/firestore/src/api/snapshot.d.ts +1 -2
  69. package/dist/lite/packages/firestore/src/api.d.ts +1 -1
  70. package/dist/lite/packages/firestore/src/core/database_info.d.ts +1 -0
  71. package/dist/lite/packages/firestore/src/core/target.d.ts +34 -5
  72. package/dist/lite/packages/firestore/src/lite-api/query.d.ts +2 -2
  73. package/dist/lite/packages/firestore/src/local/index_manager.d.ts +52 -0
  74. package/dist/lite/packages/firestore/src/local/indexeddb_index_manager.d.ts +11 -0
  75. package/dist/lite/packages/firestore/src/local/indexeddb_schema.d.ts +121 -7
  76. package/dist/lite/packages/firestore/src/local/local_serializer.d.ts +1 -1
  77. package/dist/lite/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
  78. package/dist/lite/packages/firestore/src/local/remote_document_change_buffer.d.ts +3 -12
  79. package/dist/lite/packages/firestore/src/local/simple_db.d.ts +1 -0
  80. package/dist/lite/packages/firestore/src/model/document.d.ts +7 -0
  81. package/dist/lite/packages/firestore/src/model/document_key.d.ts +1 -0
  82. package/dist/lite/packages/firestore/src/model/field_index.d.ts +87 -7
  83. package/dist/lite/packages/firestore/src/model/values.d.ts +7 -0
  84. package/dist/lite/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +1 -1
  85. package/dist/lite/packages/firestore/test/unit/model/field_index.test.d.ts +17 -0
  86. package/dist/lite/packages/firestore/test/unit/model/target.test.d.ts +17 -0
  87. package/dist/lite/packages/firestore/test/util/helpers.d.ts +8 -2
  88. package/dist/lite/private.d.ts +9 -2
  89. package/dist/packages/firestore/dist/index.esm2017.d.ts +175 -173
  90. package/dist/packages/firestore/src/api/{query.d.ts → filter.d.ts} +0 -0
  91. package/dist/packages/firestore/src/api/snapshot.d.ts +1 -2
  92. package/dist/packages/firestore/src/api.d.ts +1 -1
  93. package/dist/packages/firestore/src/core/database_info.d.ts +1 -0
  94. package/dist/packages/firestore/src/core/target.d.ts +34 -5
  95. package/dist/packages/firestore/src/lite-api/query.d.ts +2 -2
  96. package/dist/packages/firestore/src/local/index_manager.d.ts +52 -0
  97. package/dist/packages/firestore/src/local/indexeddb_index_manager.d.ts +11 -0
  98. package/dist/packages/firestore/src/local/indexeddb_schema.d.ts +121 -7
  99. package/dist/packages/firestore/src/local/local_serializer.d.ts +1 -1
  100. package/dist/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
  101. package/dist/packages/firestore/src/local/remote_document_change_buffer.d.ts +3 -12
  102. package/dist/packages/firestore/src/local/simple_db.d.ts +1 -0
  103. package/dist/packages/firestore/src/model/document.d.ts +7 -0
  104. package/dist/packages/firestore/src/model/document_key.d.ts +1 -0
  105. package/dist/packages/firestore/src/model/field_index.d.ts +87 -7
  106. package/dist/packages/firestore/src/model/values.d.ts +7 -0
  107. package/dist/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +1 -1
  108. package/dist/packages/firestore/test/unit/model/field_index.test.d.ts +17 -0
  109. package/dist/packages/firestore/test/unit/model/target.test.d.ts +17 -0
  110. package/dist/packages/firestore/test/util/helpers.d.ts +8 -2
  111. package/dist/private.d.ts +181 -16
  112. package/package.json +9 -9
@@ -8,7 +8,7 @@ import { credentials, loadPackageDefinition, Metadata } from '@grpc/grpc-js';
8
8
  import { fromJSON } from '@grpc/proto-loader';
9
9
 
10
10
  const name = "@firebase/firestore";
11
- const version$1 = "3.4.4-canary.222f264ff";
11
+ const version$1 = "3.4.4-canary.6c8eabfc5";
12
12
 
13
13
  /**
14
14
  * @license
@@ -61,7 +61,7 @@ User.GOOGLE_CREDENTIALS = new User('google-credentials-uid');
61
61
  User.FIRST_PARTY = new User('first-party-uid');
62
62
  User.MOCK_USER = new User('mock-user');
63
63
 
64
- const version = "9.6.5-canary.222f264ff";
64
+ const version = "9.6.6-canary.6c8eabfc5";
65
65
 
66
66
  /**
67
67
  * @license
@@ -1192,23 +1192,6 @@ function decodeResourcePath(path) {
1192
1192
  }
1193
1193
  return new ResourcePath(segments);
1194
1194
  }
1195
-
1196
- /**
1197
- * @license
1198
- * Copyright 2017 Google LLC
1199
- *
1200
- * Licensed under the Apache License, Version 2.0 (the "License");
1201
- * you may not use this file except in compliance with the License.
1202
- * You may obtain a copy of the License at
1203
- *
1204
- * http://www.apache.org/licenses/LICENSE-2.0
1205
- *
1206
- * Unless required by applicable law or agreed to in writing, software
1207
- * distributed under the License is distributed on an "AS IS" BASIS,
1208
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1209
- * See the License for the specific language governing permissions and
1210
- * limitations under the License.
1211
- */
1212
1195
  /**
1213
1196
  * Schema Version for the Web client:
1214
1197
  * 1. Initial version including Mutation Queue, Query Cache, and Remote
@@ -1227,6 +1210,7 @@ function decodeResourcePath(path) {
1227
1210
  * an auto-incrementing ID. This is required for Index-Free queries.
1228
1211
  * 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
1229
1212
  * 11. Add bundles and named_queries for bundle support.
1213
+ * 12. Add indexing support.
1230
1214
  */
1231
1215
  const SCHEMA_VERSION = 11;
1232
1216
  /**
@@ -1753,9 +1737,7 @@ class DbClientMetadata {
1753
1737
  DbClientMetadata.store = 'clientMetadata';
1754
1738
  /** Keys are automatically assigned via the clientId properties. */
1755
1739
  DbClientMetadata.keyPath = 'clientId';
1756
- /**
1757
- * A object representing a bundle loaded by the SDK.
1758
- */
1740
+ /** An object representing a bundle loaded by the SDK. */
1759
1741
  class DbBundle {
1760
1742
  constructor(
1761
1743
  /** The ID of the loaded bundle. */
@@ -1772,9 +1754,7 @@ class DbBundle {
1772
1754
  /** Name of the IndexedDb object store. */
1773
1755
  DbBundle.store = 'bundles';
1774
1756
  DbBundle.keyPath = 'bundleId';
1775
- /**
1776
- * A object representing a named query loaded by the SDK via a bundle.
1777
- */
1757
+ /** An object representing a named query loaded by the SDK via a bundle. */
1778
1758
  class DbNamedQuery {
1779
1759
  constructor(
1780
1760
  /** The name of the query. */
@@ -1791,6 +1771,93 @@ class DbNamedQuery {
1791
1771
  /** Name of the IndexedDb object store. */
1792
1772
  DbNamedQuery.store = 'namedQueries';
1793
1773
  DbNamedQuery.keyPath = 'name';
1774
+ /** An object representing the global configuration for a field index. */
1775
+ class DbIndexConfiguration {
1776
+ constructor(
1777
+ /** The index id for this entry. */
1778
+ indexId,
1779
+ /** The collection group this index belongs to. */
1780
+ collectionGroup,
1781
+ /** The fields to index for this index. */
1782
+ fields) {
1783
+ this.indexId = indexId;
1784
+ this.collectionGroup = collectionGroup;
1785
+ this.fields = fields;
1786
+ }
1787
+ }
1788
+ /** Name of the IndexedDb object store. */
1789
+ DbIndexConfiguration.store = 'indexConfiguration';
1790
+ DbIndexConfiguration.keyPath = 'indexId';
1791
+ /**
1792
+ * An object describing how up-to-date the index backfill is for each user and
1793
+ * index.
1794
+ */
1795
+ class DbIndexState {
1796
+ constructor(
1797
+ /** The index id for this entry. */
1798
+ indexId,
1799
+ /** The user id for this entry. */
1800
+ uid,
1801
+ /**
1802
+ * A number that indicates when the index was last updated (relative to
1803
+ * other indexes).
1804
+ */
1805
+ sequenceNumber,
1806
+ /**
1807
+ * The latest read time that has been indexed by Firestore for this field
1808
+ * index. Set to `{seconds: 0, nanos: 0}` if no documents have been indexed.
1809
+ */
1810
+ readTime,
1811
+ /**
1812
+ * The last document that has been indexed for this field index. Empty if
1813
+ * no documents have been indexed.
1814
+ */
1815
+ documentKey,
1816
+ /**
1817
+ * The largest mutation batch id that has been processed for this index. -1
1818
+ * if no mutations have been indexed.
1819
+ */
1820
+ largestBatchId) {
1821
+ this.indexId = indexId;
1822
+ this.uid = uid;
1823
+ this.sequenceNumber = sequenceNumber;
1824
+ this.readTime = readTime;
1825
+ this.documentKey = documentKey;
1826
+ this.largestBatchId = largestBatchId;
1827
+ }
1828
+ }
1829
+ /** Name of the IndexedDb object store. */
1830
+ DbIndexState.store = 'indexState';
1831
+ DbIndexState.keyPath = ['indexId', 'uid'];
1832
+ /** An object that stores the encoded entries for all documents and fields. */
1833
+ class DbIndexEntries {
1834
+ constructor(
1835
+ /** The index id for this entry. */
1836
+ indexId,
1837
+ /** The user id for this entry. */
1838
+ uid,
1839
+ /** The encoded array index value for this entry. */
1840
+ arrayValue,
1841
+ /** The encoded directional value for equality and inequality filters. */
1842
+ directionalValue,
1843
+ /** The document key this entry points to. */
1844
+ documentKey) {
1845
+ this.indexId = indexId;
1846
+ this.uid = uid;
1847
+ this.arrayValue = arrayValue;
1848
+ this.directionalValue = directionalValue;
1849
+ this.documentKey = documentKey;
1850
+ }
1851
+ }
1852
+ /** Name of the IndexedDb object store. */
1853
+ DbIndexEntries.store = 'indexEntries';
1854
+ DbIndexEntries.keyPath = [
1855
+ 'indexId',
1856
+ 'uid',
1857
+ 'arrayValue',
1858
+ 'directionalValue',
1859
+ 'documentKey'
1860
+ ];
1794
1861
  // Visible for testing
1795
1862
  const V1_STORES = [
1796
1863
  DbMutationQueue.store,
@@ -1805,7 +1872,6 @@ const V1_STORES = [
1805
1872
  // V2 is no longer usable (see comment at top of file)
1806
1873
  // Visible for testing
1807
1874
  const V3_STORES = V1_STORES;
1808
- // Visible for testing
1809
1875
  // Note: DbRemoteDocumentChanges is no longer used and dropped with v9.
1810
1876
  const V4_STORES = [...V3_STORES, DbClientMetadata.store];
1811
1877
  // V5 does not change the set of stores.
@@ -1815,6 +1881,12 @@ const V8_STORES = [...V6_STORES, DbCollectionParent.store];
1815
1881
  // V9 does not change the set of stores.
1816
1882
  // V10 does not change the set of stores.
1817
1883
  const V11_STORES = [...V8_STORES, DbBundle.store, DbNamedQuery.store];
1884
+ [
1885
+ ...V11_STORES,
1886
+ DbIndexConfiguration.store,
1887
+ DbIndexState.store,
1888
+ DbIndexEntries.store
1889
+ ];
1818
1890
  /**
1819
1891
  * The list of all default IndexedDB stores used throughout the SDK. This is
1820
1892
  * used when creating transactions so that access across all stores is done
@@ -2117,6 +2189,15 @@ class SimpleDbTransaction {
2117
2189
  this.transaction.abort();
2118
2190
  }
2119
2191
  }
2192
+ maybeCommit() {
2193
+ // If the browser supports V3 IndexedDB, we invoke commit() explicitly to
2194
+ // speed up index DB processing if the event loop remains blocks.
2195
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2196
+ const maybeV3IndexedDb = this.transaction;
2197
+ if (!this.aborted && typeof maybeV3IndexedDb.commit === 'function') {
2198
+ maybeV3IndexedDb.commit();
2199
+ }
2200
+ }
2120
2201
  /**
2121
2202
  * Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All
2122
2203
  * operations performed on the SimpleDbStore happen within the context of this
@@ -2313,6 +2394,10 @@ class SimpleDb {
2313
2394
  this.db = await this.ensureDb(action);
2314
2395
  const transaction = SimpleDbTransaction.open(this.db, action, readonly ? 'readonly' : 'readwrite', objectStores);
2315
2396
  const transactionFnResult = transactionFn(transaction)
2397
+ .next(result => {
2398
+ transaction.maybeCommit();
2399
+ return result;
2400
+ })
2316
2401
  .catch(error => {
2317
2402
  // Abort the transaction if there was an error.
2318
2403
  transaction.abort(error);
@@ -3374,6 +3459,75 @@ function getLocalWriteTime(value) {
3374
3459
  return new Timestamp(localWriteTime.seconds, localWriteTime.nanos);
3375
3460
  }
3376
3461
 
3462
+ /**
3463
+ * @license
3464
+ * Copyright 2017 Google LLC
3465
+ *
3466
+ * Licensed under the Apache License, Version 2.0 (the "License");
3467
+ * you may not use this file except in compliance with the License.
3468
+ * You may obtain a copy of the License at
3469
+ *
3470
+ * http://www.apache.org/licenses/LICENSE-2.0
3471
+ *
3472
+ * Unless required by applicable law or agreed to in writing, software
3473
+ * distributed under the License is distributed on an "AS IS" BASIS,
3474
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3475
+ * See the License for the specific language governing permissions and
3476
+ * limitations under the License.
3477
+ */
3478
+ class DatabaseInfo {
3479
+ /**
3480
+ * Constructs a DatabaseInfo using the provided host, databaseId and
3481
+ * persistenceKey.
3482
+ *
3483
+ * @param databaseId - The database to use.
3484
+ * @param appId - The Firebase App Id.
3485
+ * @param persistenceKey - A unique identifier for this Firestore's local
3486
+ * storage (used in conjunction with the databaseId).
3487
+ * @param host - The Firestore backend host to connect to.
3488
+ * @param ssl - Whether to use SSL when connecting.
3489
+ * @param forceLongPolling - Whether to use the forceLongPolling option
3490
+ * when using WebChannel as the network transport.
3491
+ * @param autoDetectLongPolling - Whether to use the detectBufferingProxy
3492
+ * option when using WebChannel as the network transport.
3493
+ * @param useFetchStreams Whether to use the Fetch API instead of
3494
+ * XMLHTTPRequest
3495
+ */
3496
+ constructor(databaseId, appId, persistenceKey, host, ssl, forceLongPolling, autoDetectLongPolling, useFetchStreams) {
3497
+ this.databaseId = databaseId;
3498
+ this.appId = appId;
3499
+ this.persistenceKey = persistenceKey;
3500
+ this.host = host;
3501
+ this.ssl = ssl;
3502
+ this.forceLongPolling = forceLongPolling;
3503
+ this.autoDetectLongPolling = autoDetectLongPolling;
3504
+ this.useFetchStreams = useFetchStreams;
3505
+ }
3506
+ }
3507
+ /** The default database name for a project. */
3508
+ const DEFAULT_DATABASE_NAME = '(default)';
3509
+ /**
3510
+ * Represents the database ID a Firestore client is associated with.
3511
+ * @internal
3512
+ */
3513
+ class DatabaseId {
3514
+ constructor(projectId, database) {
3515
+ this.projectId = projectId;
3516
+ this.database = database ? database : DEFAULT_DATABASE_NAME;
3517
+ }
3518
+ static empty() {
3519
+ return new DatabaseId('', '');
3520
+ }
3521
+ get isDefaultDatabase() {
3522
+ return this.database === DEFAULT_DATABASE_NAME;
3523
+ }
3524
+ isEqual(other) {
3525
+ return (other instanceof DatabaseId &&
3526
+ other.projectId === this.projectId &&
3527
+ other.database === this.database);
3528
+ }
3529
+ }
3530
+
3377
3531
  /**
3378
3532
  * @license
3379
3533
  * Copyright 2017 Google LLC
@@ -3445,6 +3599,9 @@ class DocumentKey {
3445
3599
  static fromName(name) {
3446
3600
  return new DocumentKey(ResourcePath.fromString(name).popFirst(5));
3447
3601
  }
3602
+ static empty() {
3603
+ return new DocumentKey(ResourcePath.emptyPath());
3604
+ }
3448
3605
  /** Returns true if the document is in the specified collectionId. */
3449
3606
  hasCollectionId(collectionId) {
3450
3607
  return (this.path.length >= 2 &&
@@ -4093,10 +4250,11 @@ function extractFieldMask(value) {
4093
4250
  * from all views.
4094
4251
  */
4095
4252
  class MutableDocument {
4096
- constructor(key, documentType, version, data, documentState) {
4253
+ constructor(key, documentType, version, readTime, data, documentState) {
4097
4254
  this.key = key;
4098
4255
  this.documentType = documentType;
4099
4256
  this.version = version;
4257
+ this.readTime = readTime;
4100
4258
  this.data = data;
4101
4259
  this.documentState = documentState;
4102
4260
  }
@@ -4105,18 +4263,18 @@ class MutableDocument {
4105
4263
  * base document for mutations.
4106
4264
  */
4107
4265
  static newInvalidDocument(documentKey) {
4108
- return new MutableDocument(documentKey, 0 /* INVALID */, SnapshotVersion.min(), ObjectValue.empty(), 0 /* SYNCED */);
4266
+ return new MutableDocument(documentKey, 0 /* INVALID */, SnapshotVersion.min(), SnapshotVersion.min(), ObjectValue.empty(), 0 /* SYNCED */);
4109
4267
  }
4110
4268
  /**
4111
4269
  * Creates a new document that is known to exist with the given data at the
4112
4270
  * given version.
4113
4271
  */
4114
4272
  static newFoundDocument(documentKey, version, value) {
4115
- return new MutableDocument(documentKey, 1 /* FOUND_DOCUMENT */, version, value, 0 /* SYNCED */);
4273
+ return new MutableDocument(documentKey, 1 /* FOUND_DOCUMENT */, version, SnapshotVersion.min(), value, 0 /* SYNCED */);
4116
4274
  }
4117
4275
  /** Creates a new document that is known to not exist at the given version. */
4118
4276
  static newNoDocument(documentKey, version) {
4119
- return new MutableDocument(documentKey, 2 /* NO_DOCUMENT */, version, ObjectValue.empty(), 0 /* SYNCED */);
4277
+ return new MutableDocument(documentKey, 2 /* NO_DOCUMENT */, version, SnapshotVersion.min(), ObjectValue.empty(), 0 /* SYNCED */);
4120
4278
  }
4121
4279
  /**
4122
4280
  * Creates a new document that is known to exist at the given version but
@@ -4124,7 +4282,7 @@ class MutableDocument {
4124
4282
  * base document).
4125
4283
  */
4126
4284
  static newUnknownDocument(documentKey, version) {
4127
- return new MutableDocument(documentKey, 3 /* UNKNOWN_DOCUMENT */, version, ObjectValue.empty(), 2 /* HAS_COMMITTED_MUTATIONS */);
4285
+ return new MutableDocument(documentKey, 3 /* UNKNOWN_DOCUMENT */, version, SnapshotVersion.min(), ObjectValue.empty(), 2 /* HAS_COMMITTED_MUTATIONS */);
4128
4286
  }
4129
4287
  /**
4130
4288
  * Changes the document type to indicate that it exists and that its version
@@ -4168,6 +4326,10 @@ class MutableDocument {
4168
4326
  this.documentState = 1 /* HAS_LOCAL_MUTATIONS */;
4169
4327
  return this;
4170
4328
  }
4329
+ setReadTime(readTime) {
4330
+ this.readTime = readTime;
4331
+ return this;
4332
+ }
4171
4333
  get hasLocalMutations() {
4172
4334
  return this.documentState === 1 /* HAS_LOCAL_MUTATIONS */;
4173
4335
  }
@@ -4198,7 +4360,7 @@ class MutableDocument {
4198
4360
  this.data.isEqual(other.data));
4199
4361
  }
4200
4362
  mutableCopy() {
4201
- return new MutableDocument(this.key, this.documentType, this.version, this.data.clone(), this.documentState);
4363
+ return new MutableDocument(this.key, this.documentType, this.version, this.readTime, this.data.clone(), this.documentState);
4202
4364
  }
4203
4365
  toString() {
4204
4366
  return (`Document(${this.key}, ${this.version}, ${JSON.stringify(this.data.value)}, ` +
@@ -4221,6 +4383,125 @@ function compareDocumentsByField(field, d1, d2) {
4221
4383
  }
4222
4384
  }
4223
4385
 
4386
+ /**
4387
+ * @license
4388
+ * Copyright 2021 Google LLC
4389
+ *
4390
+ * Licensed under the Apache License, Version 2.0 (the "License");
4391
+ * you may not use this file except in compliance with the License.
4392
+ * You may obtain a copy of the License at
4393
+ *
4394
+ * http://www.apache.org/licenses/LICENSE-2.0
4395
+ *
4396
+ * Unless required by applicable law or agreed to in writing, software
4397
+ * distributed under the License is distributed on an "AS IS" BASIS,
4398
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4399
+ * See the License for the specific language governing permissions and
4400
+ * limitations under the License.
4401
+ */
4402
+ /**
4403
+ * The initial mutation batch id for each index. Gets updated during index
4404
+ * backfill.
4405
+ */
4406
+ const INITIAL_LARGEST_BATCH_ID = -1;
4407
+ /**
4408
+ * The initial sequence number for each index. Gets updated during index
4409
+ * backfill.
4410
+ */
4411
+ const INITIAL_SEQUENCE_NUMBER = 0;
4412
+ /**
4413
+ * An index definition for field indexes in Firestore.
4414
+ *
4415
+ * Every index is associated with a collection. The definition contains a list
4416
+ * of fields and their index kind (which can be `ASCENDING`, `DESCENDING` or
4417
+ * `CONTAINS` for ArrayContains/ArrayContainsAny queries).
4418
+ *
4419
+ * Unlike the backend, the SDK does not differentiate between collection or
4420
+ * collection group-scoped indices. Every index can be used for both single
4421
+ * collection and collection group queries.
4422
+ */
4423
+ class FieldIndex {
4424
+ constructor(
4425
+ /**
4426
+ * The index ID. Returns -1 if the index ID is not available (e.g. the index
4427
+ * has not yet been persisted).
4428
+ */
4429
+ indexId,
4430
+ /** The collection ID this index applies to. */
4431
+ collectionGroup,
4432
+ /** The field segments for this index. */
4433
+ segments,
4434
+ /** Shows how up-to-date the index is for the current user. */
4435
+ indexState) {
4436
+ this.indexId = indexId;
4437
+ this.collectionGroup = collectionGroup;
4438
+ this.segments = segments;
4439
+ this.indexState = indexState;
4440
+ }
4441
+ }
4442
+ /** An ID for an index that has not yet been added to persistence. */
4443
+ FieldIndex.UNKNOWN_ID = -1;
4444
+ /** An index component consisting of field path and index type. */
4445
+ class IndexSegment {
4446
+ constructor(
4447
+ /** The field path of the component. */
4448
+ fieldPath,
4449
+ /** The fields sorting order. */
4450
+ kind) {
4451
+ this.fieldPath = fieldPath;
4452
+ this.kind = kind;
4453
+ }
4454
+ }
4455
+ /**
4456
+ * Stores the "high water mark" that indicates how updated the Index is for the
4457
+ * current user.
4458
+ */
4459
+ class IndexState {
4460
+ constructor(
4461
+ /**
4462
+ * Indicates when the index was last updated (relative to other indexes).
4463
+ */
4464
+ sequenceNumber,
4465
+ /** The the latest indexed read time, document and batch id. */
4466
+ offset) {
4467
+ this.sequenceNumber = sequenceNumber;
4468
+ this.offset = offset;
4469
+ }
4470
+ /** The state of an index that has not yet been backfilled. */
4471
+ static empty() {
4472
+ return new IndexState(INITIAL_SEQUENCE_NUMBER, IndexOffset.min());
4473
+ }
4474
+ }
4475
+ /**
4476
+ * Stores the latest read time, document and batch ID that were processed for an
4477
+ * index.
4478
+ */
4479
+ class IndexOffset {
4480
+ constructor(
4481
+ /**
4482
+ * The latest read time version that has been indexed by Firestore for this
4483
+ * field index.
4484
+ */
4485
+ readTime,
4486
+ /**
4487
+ * The key of the last document that was indexed for this query. Use
4488
+ * `DocumentKey.empty()` if no document has been indexed.
4489
+ */
4490
+ documentKey,
4491
+ /*
4492
+ * The largest mutation batch id that's been processed by Firestore.
4493
+ */
4494
+ largestBatchId) {
4495
+ this.readTime = readTime;
4496
+ this.documentKey = documentKey;
4497
+ this.largestBatchId = largestBatchId;
4498
+ }
4499
+ /** The state of an index that has not yet been backfilled. */
4500
+ static min() {
4501
+ return new IndexOffset(SnapshotVersion.min(), DocumentKey.empty(), INITIAL_LARGEST_BATCH_ID);
4502
+ }
4503
+ }
4504
+
4224
4505
  /**
4225
4506
  * @license
4226
4507
  * Copyright 2019 Google LLC
@@ -4264,27 +4545,29 @@ function newTarget(path, collectionGroup = null, orderBy = [], filters = [], lim
4264
4545
  function canonifyTarget(target) {
4265
4546
  const targetImpl = debugCast(target);
4266
4547
  if (targetImpl.memoizedCanonicalId === null) {
4267
- let canonicalId = targetImpl.path.canonicalString();
4548
+ let str = targetImpl.path.canonicalString();
4268
4549
  if (targetImpl.collectionGroup !== null) {
4269
- canonicalId += '|cg:' + targetImpl.collectionGroup;
4550
+ str += '|cg:' + targetImpl.collectionGroup;
4270
4551
  }
4271
- canonicalId += '|f:';
4272
- canonicalId += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
4273
- canonicalId += '|ob:';
4274
- canonicalId += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
4552
+ str += '|f:';
4553
+ str += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
4554
+ str += '|ob:';
4555
+ str += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
4275
4556
  if (!isNullOrUndefined(targetImpl.limit)) {
4276
- canonicalId += '|l:';
4277
- canonicalId += targetImpl.limit;
4557
+ str += '|l:';
4558
+ str += targetImpl.limit;
4278
4559
  }
4279
4560
  if (targetImpl.startAt) {
4280
- canonicalId += '|lb:';
4281
- canonicalId += canonifyBound(targetImpl.startAt);
4561
+ str += '|lb:';
4562
+ str += targetImpl.startAt.inclusive ? 'b:' : 'a:';
4563
+ str += targetImpl.startAt.position.map(p => canonicalId(p)).join(',');
4282
4564
  }
4283
4565
  if (targetImpl.endAt) {
4284
- canonicalId += '|ub:';
4285
- canonicalId += canonifyBound(targetImpl.endAt);
4566
+ str += '|ub:';
4567
+ str += targetImpl.endAt.inclusive ? 'a:' : 'b:';
4568
+ str += targetImpl.endAt.position.map(p => canonicalId(p)).join(',');
4286
4569
  }
4287
- targetImpl.memoizedCanonicalId = canonicalId;
4570
+ targetImpl.memoizedCanonicalId = str;
4288
4571
  }
4289
4572
  return targetImpl.memoizedCanonicalId;
4290
4573
  }
@@ -4307,10 +4590,14 @@ function stringifyTarget(target) {
4307
4590
  .join(', ')}]`;
4308
4591
  }
4309
4592
  if (target.startAt) {
4310
- str += ', startAt: ' + canonifyBound(target.startAt);
4593
+ str += ', startAt: ';
4594
+ str += target.startAt.inclusive ? 'b:' : 'a:';
4595
+ str += target.startAt.position.map(p => canonicalId(p)).join(',');
4311
4596
  }
4312
4597
  if (target.endAt) {
4313
- str += ', endAt: ' + canonifyBound(target.endAt);
4598
+ str += ', endAt: ';
4599
+ str += target.endAt.inclusive ? 'a:' : 'b:';
4600
+ str += target.endAt.position.map(p => canonicalId(p)).join(',');
4314
4601
  }
4315
4602
  return `Target(${str})`;
4316
4603
  }
@@ -4345,7 +4632,7 @@ function targetEquals(left, right) {
4345
4632
  }
4346
4633
  return boundEquals(left.endAt, right.endAt);
4347
4634
  }
4348
- function isDocumentTarget(target) {
4635
+ function targetIsDocumentTarget(target) {
4349
4636
  return (DocumentKey.isDocumentKey(target.path) &&
4350
4637
  target.collectionGroup === null &&
4351
4638
  target.filters.length === 0);
@@ -4548,17 +4835,11 @@ class ArrayContainsAnyFilter extends FieldFilter {
4548
4835
  * just after the provided values.
4549
4836
  */
4550
4837
  class Bound {
4551
- constructor(position, before) {
4838
+ constructor(position, inclusive) {
4552
4839
  this.position = position;
4553
- this.before = before;
4840
+ this.inclusive = inclusive;
4554
4841
  }
4555
4842
  }
4556
- function canonifyBound(bound) {
4557
- // TODO(b/29183165): Make this collision robust.
4558
- return `${bound.before ? 'b' : 'a'}:${bound.position
4559
- .map(p => canonicalId(p))
4560
- .join(',')}`;
4561
- }
4562
4843
  /**
4563
4844
  * An ordering on a field, in some Direction. Direction defaults to ASCENDING.
4564
4845
  */
@@ -4578,11 +4859,7 @@ function stringifyOrderBy(orderBy) {
4578
4859
  function orderByEquals(left, right) {
4579
4860
  return left.dir === right.dir && left.field.isEqual(right.field);
4580
4861
  }
4581
- /**
4582
- * Returns true if a document sorts before a bound using the provided sort
4583
- * order.
4584
- */
4585
- function sortsBeforeDocument(bound, orderBy, doc) {
4862
+ function boundCompareToDocument(bound, orderBy, doc) {
4586
4863
  let comparison = 0;
4587
4864
  for (let i = 0; i < bound.position.length; i++) {
4588
4865
  const orderByComponent = orderBy[i];
@@ -4601,7 +4878,23 @@ function sortsBeforeDocument(bound, orderBy, doc) {
4601
4878
  break;
4602
4879
  }
4603
4880
  }
4604
- return bound.before ? comparison <= 0 : comparison < 0;
4881
+ return comparison;
4882
+ }
4883
+ /**
4884
+ * Returns true if a document sorts after a bound using the provided sort
4885
+ * order.
4886
+ */
4887
+ function boundSortsAfterDocument(bound, orderBy, doc) {
4888
+ const comparison = boundCompareToDocument(bound, orderBy, doc);
4889
+ return bound.inclusive ? comparison >= 0 : comparison > 0;
4890
+ }
4891
+ /**
4892
+ * Returns true if a document sorts before a bound using the provided sort
4893
+ * order.
4894
+ */
4895
+ function boundSortsBeforeDocument(bound, orderBy, doc) {
4896
+ const comparison = boundCompareToDocument(bound, orderBy, doc);
4897
+ return bound.inclusive ? comparison <= 0 : comparison < 0;
4605
4898
  }
4606
4899
  function boundEquals(left, right) {
4607
4900
  if (left === null) {
@@ -4610,7 +4903,7 @@ function boundEquals(left, right) {
4610
4903
  else if (right === null) {
4611
4904
  return false;
4612
4905
  }
4613
- if (left.before !== right.before ||
4906
+ if (left.inclusive !== right.inclusive ||
4614
4907
  left.position.length !== right.position.length) {
4615
4908
  return false;
4616
4909
  }
@@ -4814,10 +5107,10 @@ function queryToTarget(query) {
4814
5107
  }
4815
5108
  // We need to swap the cursors to match the now-flipped query ordering.
4816
5109
  const startAt = queryImpl.endAt
4817
- ? new Bound(queryImpl.endAt.position, !queryImpl.endAt.before)
5110
+ ? new Bound(queryImpl.endAt.position, !queryImpl.endAt.inclusive)
4818
5111
  : null;
4819
5112
  const endAt = queryImpl.startAt
4820
- ? new Bound(queryImpl.startAt.position, !queryImpl.startAt.before)
5113
+ ? new Bound(queryImpl.startAt.position, !queryImpl.startAt.inclusive)
4821
5114
  : null;
4822
5115
  // Now return as a LimitType.First query.
4823
5116
  queryImpl.memoizedTarget = newTarget(queryImpl.path, queryImpl.collectionGroup, orderBys, queryImpl.filters, queryImpl.limit, startAt, endAt);
@@ -4905,11 +5198,11 @@ function queryMatchesFilters(query, doc) {
4905
5198
  /** Makes sure a document is within the bounds, if provided. */
4906
5199
  function queryMatchesBounds(query, doc) {
4907
5200
  if (query.startAt &&
4908
- !sortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
5201
+ !boundSortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
4909
5202
  return false;
4910
5203
  }
4911
5204
  if (query.endAt &&
4912
- sortsBeforeDocument(query.endAt, queryOrderBy(query), doc)) {
5205
+ !boundSortsAfterDocument(query.endAt, queryOrderBy(query), doc)) {
4913
5206
  return false;
4914
5207
  }
4915
5208
  return true;
@@ -6990,7 +7283,7 @@ class WatchChangeAggregator {
6990
7283
  const targetData = this.targetDataForActiveTarget(targetId);
6991
7284
  if (targetData) {
6992
7285
  const target = targetData.target;
6993
- if (isDocumentTarget(target)) {
7286
+ if (targetIsDocumentTarget(target)) {
6994
7287
  if (expectedCount === 0) {
6995
7288
  // The existence filter told us the document does not exist. We deduce
6996
7289
  // that this document does not exist and apply a deleted document to
@@ -7025,7 +7318,7 @@ class WatchChangeAggregator {
7025
7318
  this.targetStates.forEach((targetState, targetId) => {
7026
7319
  const targetData = this.targetDataForActiveTarget(targetId);
7027
7320
  if (targetData) {
7028
- if (targetState.current && isDocumentTarget(targetData.target)) {
7321
+ if (targetState.current && targetIsDocumentTarget(targetData.target)) {
7029
7322
  // Document queries for document that don't exist can produce an empty
7030
7323
  // result set. To update our local cache, we synthesize a document
7031
7324
  // delete if we have not previously received the document. This
@@ -7068,6 +7361,7 @@ class WatchChangeAggregator {
7068
7361
  resolvedLimboDocuments = resolvedLimboDocuments.add(key);
7069
7362
  }
7070
7363
  });
7364
+ this.pendingDocumentUpdates.forEach((_, doc) => doc.setReadTime(snapshotVersion));
7071
7365
  const remoteEvent = new RemoteEvent(snapshotVersion, targetChanges, this.pendingTargetResets, this.pendingDocumentUpdates, resolvedLimboDocuments);
7072
7366
  this.pendingDocumentUpdates = mutableDocumentMap();
7073
7367
  this.pendingDocumentTargetMapping = documentTargetMap();
@@ -7787,10 +8081,10 @@ function toQueryTarget(serializer, target) {
7787
8081
  result.structuredQuery.limit = limit;
7788
8082
  }
7789
8083
  if (target.startAt) {
7790
- result.structuredQuery.startAt = toCursor(target.startAt);
8084
+ result.structuredQuery.startAt = toStartAtCursor(target.startAt);
7791
8085
  }
7792
8086
  if (target.endAt) {
7793
- result.structuredQuery.endAt = toCursor(target.endAt);
8087
+ result.structuredQuery.endAt = toEndAtCursor(target.endAt);
7794
8088
  }
7795
8089
  return result;
7796
8090
  }
@@ -7823,11 +8117,11 @@ function convertQueryTargetToQuery(target) {
7823
8117
  }
7824
8118
  let startAt = null;
7825
8119
  if (query.startAt) {
7826
- startAt = fromCursor(query.startAt);
8120
+ startAt = fromStartAtCursor(query.startAt);
7827
8121
  }
7828
8122
  let endAt = null;
7829
8123
  if (query.endAt) {
7830
- endAt = fromCursor(query.endAt);
8124
+ endAt = fromEndAtCursor(query.endAt);
7831
8125
  }
7832
8126
  return newQuery(path, collectionGroup, orderBy, filterBy, limit, "F" /* First */, startAt, endAt);
7833
8127
  }
@@ -7860,7 +8154,7 @@ function toLabel(serializer, purpose) {
7860
8154
  function toTarget(serializer, targetData) {
7861
8155
  let result;
7862
8156
  const target = targetData.target;
7863
- if (isDocumentTarget(target)) {
8157
+ if (targetIsDocumentTarget(target)) {
7864
8158
  result = { documents: toDocumentsTarget(serializer, target) };
7865
8159
  }
7866
8160
  else {
@@ -7918,16 +8212,27 @@ function toOrder(orderBys) {
7918
8212
  function fromOrder(orderBys) {
7919
8213
  return orderBys.map(order => fromPropertyOrder(order));
7920
8214
  }
7921
- function toCursor(cursor) {
8215
+ function toStartAtCursor(cursor) {
8216
+ return {
8217
+ before: cursor.inclusive,
8218
+ values: cursor.position
8219
+ };
8220
+ }
8221
+ function toEndAtCursor(cursor) {
7922
8222
  return {
7923
- before: cursor.before,
8223
+ before: !cursor.inclusive,
7924
8224
  values: cursor.position
7925
8225
  };
7926
8226
  }
7927
- function fromCursor(cursor) {
7928
- const before = !!cursor.before;
8227
+ function fromStartAtCursor(cursor) {
8228
+ const inclusive = !!cursor.before;
7929
8229
  const position = cursor.values || [];
7930
- return new Bound(position, before);
8230
+ return new Bound(position, inclusive);
8231
+ }
8232
+ function fromEndAtCursor(cursor) {
8233
+ const inclusive = !cursor.before;
8234
+ const position = cursor.values || [];
8235
+ return new Bound(position, inclusive);
7931
8236
  }
7932
8237
  // visible for testing
7933
8238
  function toDirection(dir) {
@@ -8188,29 +8493,34 @@ class LocalSerializer {
8188
8493
  }
8189
8494
  /** Decodes a remote document from storage locally to a Document. */
8190
8495
  function fromDbRemoteDocument(localSerializer, remoteDoc) {
8496
+ let doc;
8191
8497
  if (remoteDoc.document) {
8192
- return fromDocument(localSerializer.remoteSerializer, remoteDoc.document, !!remoteDoc.hasCommittedMutations);
8498
+ doc = fromDocument(localSerializer.remoteSerializer, remoteDoc.document, !!remoteDoc.hasCommittedMutations);
8193
8499
  }
8194
8500
  else if (remoteDoc.noDocument) {
8195
8501
  const key = DocumentKey.fromSegments(remoteDoc.noDocument.path);
8196
8502
  const version = fromDbTimestamp(remoteDoc.noDocument.readTime);
8197
- const document = MutableDocument.newNoDocument(key, version);
8198
- return remoteDoc.hasCommittedMutations
8199
- ? document.setHasCommittedMutations()
8200
- : document;
8503
+ doc = MutableDocument.newNoDocument(key, version);
8504
+ if (remoteDoc.hasCommittedMutations) {
8505
+ doc.setHasCommittedMutations();
8506
+ }
8201
8507
  }
8202
8508
  else if (remoteDoc.unknownDocument) {
8203
8509
  const key = DocumentKey.fromSegments(remoteDoc.unknownDocument.path);
8204
8510
  const version = fromDbTimestamp(remoteDoc.unknownDocument.version);
8205
- return MutableDocument.newUnknownDocument(key, version);
8511
+ doc = MutableDocument.newUnknownDocument(key, version);
8206
8512
  }
8207
8513
  else {
8208
8514
  return fail();
8209
8515
  }
8516
+ if (remoteDoc.readTime) {
8517
+ doc.setReadTime(fromDbTimestampKey(remoteDoc.readTime));
8518
+ }
8519
+ return doc;
8210
8520
  }
8211
8521
  /** Encodes a document for storage locally. */
8212
- function toDbRemoteDocument(localSerializer, document, readTime) {
8213
- const dbReadTime = toDbTimestampKey(readTime);
8522
+ function toDbRemoteDocument(localSerializer, document) {
8523
+ const dbReadTime = toDbTimestampKey(document.readTime);
8214
8524
  const parentPath = document.key.path.popLast().toArray();
8215
8525
  if (document.isFoundDocument()) {
8216
8526
  const doc = toDocument(localSerializer.remoteSerializer, document);
@@ -8221,10 +8531,10 @@ function toDbRemoteDocument(localSerializer, document, readTime) {
8221
8531
  }
8222
8532
  else if (document.isNoDocument()) {
8223
8533
  const path = document.key.path.toArray();
8224
- const readTime = toDbTimestamp(document.version);
8534
+ const version = toDbTimestamp(document.version);
8225
8535
  const hasCommittedMutations = document.hasCommittedMutations;
8226
8536
  return new DbRemoteDocument(
8227
- /* unknownDocument= */ null, new DbNoDocument(path, readTime),
8537
+ /* unknownDocument= */ null, new DbNoDocument(path, version),
8228
8538
  /* document= */ null, hasCommittedMutations, dbReadTime, parentPath);
8229
8539
  }
8230
8540
  else if (document.isUnknownDocument()) {
@@ -8305,7 +8615,7 @@ function toDbTarget(localSerializer, targetData) {
8305
8615
  const dbTimestamp = toDbTimestamp(targetData.snapshotVersion);
8306
8616
  const dbLastLimboFreeTimestamp = toDbTimestamp(targetData.lastLimboFreeSnapshotVersion);
8307
8617
  let queryProto;
8308
- if (isDocumentTarget(targetData.target)) {
8618
+ if (targetIsDocumentTarget(targetData.target)) {
8309
8619
  queryProto = toDocumentsTarget(localSerializer.remoteSerializer, targetData.target);
8310
8620
  }
8311
8621
  else {
@@ -8475,6 +8785,38 @@ class MemoryIndexManager {
8475
8785
  getCollectionParents(transaction, collectionId) {
8476
8786
  return PersistencePromise.resolve(this.collectionParentIndex.getEntries(collectionId));
8477
8787
  }
8788
+ addFieldIndex(transaction, index) {
8789
+ // Field indices are not supported with memory persistence.
8790
+ return PersistencePromise.resolve();
8791
+ }
8792
+ deleteFieldIndex(transaction, index) {
8793
+ // Field indices are not supported with memory persistence.
8794
+ return PersistencePromise.resolve();
8795
+ }
8796
+ getDocumentsMatchingTarget(transaction, fieldIndex, target) {
8797
+ // Field indices are not supported with memory persistence.
8798
+ return PersistencePromise.resolve(documentKeySet());
8799
+ }
8800
+ getFieldIndex(transaction, target) {
8801
+ // Field indices are not supported with memory persistence.
8802
+ return PersistencePromise.resolve(null);
8803
+ }
8804
+ getFieldIndexes(transaction, collectionGroup) {
8805
+ // Field indices are not supported with memory persistence.
8806
+ return PersistencePromise.resolve([]);
8807
+ }
8808
+ getNextCollectionGroupToUpdate(transaction) {
8809
+ // Field indices are not supported with memory persistence.
8810
+ return PersistencePromise.resolve(null);
8811
+ }
8812
+ updateCollectionGroup(transaction, collectionGroup, offset) {
8813
+ // Field indices are not supported with memory persistence.
8814
+ return PersistencePromise.resolve();
8815
+ }
8816
+ updateIndexEntries(transaction, documents) {
8817
+ // Field indices are not supported with memory persistence.
8818
+ return PersistencePromise.resolve();
8819
+ }
8478
8820
  }
8479
8821
  /**
8480
8822
  * Internal implementation of the collection-parent index exposed by MemoryIndexManager.
@@ -8583,6 +8925,38 @@ class IndexedDbIndexManager {
8583
8925
  return parentPaths;
8584
8926
  });
8585
8927
  }
8928
+ addFieldIndex(transaction, index) {
8929
+ // TODO(indexing): Implement
8930
+ return PersistencePromise.resolve();
8931
+ }
8932
+ deleteFieldIndex(transaction, index) {
8933
+ // TODO(indexing): Implement
8934
+ return PersistencePromise.resolve();
8935
+ }
8936
+ getDocumentsMatchingTarget(transaction, fieldIndex, target) {
8937
+ // TODO(indexing): Implement
8938
+ return PersistencePromise.resolve(documentKeySet());
8939
+ }
8940
+ getFieldIndex(transaction, target) {
8941
+ // TODO(indexing): Implement
8942
+ return PersistencePromise.resolve(null);
8943
+ }
8944
+ getFieldIndexes(transaction, collectionGroup) {
8945
+ // TODO(indexing): Implement
8946
+ return PersistencePromise.resolve([]);
8947
+ }
8948
+ getNextCollectionGroupToUpdate(transaction) {
8949
+ // TODO(indexing): Implement
8950
+ return PersistencePromise.resolve(null);
8951
+ }
8952
+ updateCollectionGroup(transaction, collectionGroup, offset) {
8953
+ // TODO(indexing): Implement
8954
+ return PersistencePromise.resolve();
8955
+ }
8956
+ updateIndexEntries(transaction, documents) {
8957
+ // TODO(indexing): Implement
8958
+ return PersistencePromise.resolve();
8959
+ }
8586
8960
  }
8587
8961
  /**
8588
8962
  * Helper to get a typed SimpleDbStore for the collectionParents
@@ -9753,7 +10127,7 @@ class IndexedDbLruDelegateImpl {
9753
10127
  // Our size accounting requires us to read all documents before
9754
10128
  // removing them.
9755
10129
  return changeBuffer.getEntry(txn, docKey).next(() => {
9756
- changeBuffer.removeEntry(docKey);
10130
+ changeBuffer.removeEntry(docKey, SnapshotVersion.min());
9757
10131
  return documentTargetStore(txn).delete(sentinelKey$1(docKey));
9758
10132
  });
9759
10133
  }
@@ -9966,27 +10340,19 @@ class ObjectMap {
9966
10340
  */
9967
10341
  class RemoteDocumentChangeBuffer {
9968
10342
  constructor() {
9969
- // A mapping of document key to the new cache entry that should be written (or null if any
9970
- // existing cache entry should be removed).
10343
+ // A mapping of document key to the new cache entry that should be written.
9971
10344
  this.changes = new ObjectMap(key => key.toString(), (l, r) => l.isEqual(r));
9972
10345
  this.changesApplied = false;
9973
10346
  }
9974
- getReadTime(key) {
9975
- const change = this.changes.get(key);
9976
- if (change) {
9977
- return change.readTime;
9978
- }
9979
- return SnapshotVersion.min();
9980
- }
9981
10347
  /**
9982
10348
  * Buffers a `RemoteDocumentCache.addEntry()` call.
9983
10349
  *
9984
10350
  * You can only modify documents that have already been retrieved via
9985
10351
  * `getEntry()/getEntries()` (enforced via IndexedDbs `apply()`).
9986
10352
  */
9987
- addEntry(document, readTime) {
10353
+ addEntry(document) {
9988
10354
  this.assertNotApplied();
9989
- this.changes.set(document.key, { document, readTime });
10355
+ this.changes.set(document.key, document);
9990
10356
  }
9991
10357
  /**
9992
10358
  * Buffers a `RemoteDocumentCache.removeEntry()` call.
@@ -9994,12 +10360,9 @@ class RemoteDocumentChangeBuffer {
9994
10360
  * You can only remove documents that have already been retrieved via
9995
10361
  * `getEntry()/getEntries()` (enforced via IndexedDbs `apply()`).
9996
10362
  */
9997
- removeEntry(key, readTime = null) {
10363
+ removeEntry(key, readTime) {
9998
10364
  this.assertNotApplied();
9999
- this.changes.set(key, {
10000
- document: MutableDocument.newInvalidDocument(key),
10001
- readTime
10002
- });
10365
+ this.changes.set(key, MutableDocument.newInvalidDocument(key).setReadTime(readTime));
10003
10366
  }
10004
10367
  /**
10005
10368
  * Looks up an entry in the cache. The buffered changes will first be checked,
@@ -10016,7 +10379,7 @@ class RemoteDocumentChangeBuffer {
10016
10379
  this.assertNotApplied();
10017
10380
  const bufferedEntry = this.changes.get(documentKey);
10018
10381
  if (bufferedEntry !== undefined) {
10019
- return PersistencePromise.resolve(bufferedEntry.document);
10382
+ return PersistencePromise.resolve(bufferedEntry);
10020
10383
  }
10021
10384
  else {
10022
10385
  return this.getFromCache(transaction, documentKey);
@@ -10227,7 +10590,7 @@ class IndexedDbRemoteDocumentCacheImpl {
10227
10590
  if (key.length !== immediateChildrenPathLength) {
10228
10591
  return;
10229
10592
  }
10230
- const document = fromDbRemoteDocument(this.serializer, dbRemoteDoc);
10593
+ const document = this.maybeDecodeDocument(DocumentKey.fromSegments(key), dbRemoteDoc);
10231
10594
  if (!query.path.isPrefixOf(document.key.path)) {
10232
10595
  control.done();
10233
10596
  }
@@ -10255,8 +10618,8 @@ class IndexedDbRemoteDocumentCacheImpl {
10255
10618
  return documentGlobalStore(txn).put(DbRemoteDocumentGlobal.key, metadata);
10256
10619
  }
10257
10620
  /**
10258
- * Decodes `remoteDoc` and returns the document (or null, if the document
10259
- * corresponds to the format used for sentinel deletes).
10621
+ * Decodes `dbRemoteDoc` and returns the document (or an invalid document if
10622
+ * the document corresponds to the format used for sentinel deletes).
10260
10623
  */
10261
10624
  maybeDecodeDocument(documentKey, dbRemoteDoc) {
10262
10625
  if (dbRemoteDoc) {
@@ -10350,8 +10713,8 @@ class IndexedDbRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
10350
10713
  let collectionParents = new SortedSet((l, r) => primitiveComparator(l.canonicalString(), r.canonicalString()));
10351
10714
  this.changes.forEach((key, documentChange) => {
10352
10715
  const previousSize = this.documentSizes.get(key);
10353
- if (documentChange.document.isValidDocument()) {
10354
- const doc = toDbRemoteDocument(this.documentCache.serializer, documentChange.document, this.getReadTime(key));
10716
+ if (documentChange.isValidDocument()) {
10717
+ const doc = toDbRemoteDocument(this.documentCache.serializer, documentChange);
10355
10718
  collectionParents = collectionParents.add(key.path.popLast());
10356
10719
  const size = dbDocumentSize(doc);
10357
10720
  sizeDelta += size - previousSize;
@@ -10364,7 +10727,7 @@ class IndexedDbRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
10364
10727
  // RemoteDocumentCache. This entry is represented by a NoDocument
10365
10728
  // with a version of 0 and ignored by `maybeDecodeDocument()` but
10366
10729
  // preserved in `getNewDocumentChanges()`.
10367
- const deletedDoc = toDbRemoteDocument(this.documentCache.serializer, MutableDocument.newNoDocument(key, SnapshotVersion.min()), this.getReadTime(key));
10730
+ const deletedDoc = toDbRemoteDocument(this.documentCache.serializer, documentChange.convertToNoDocument(SnapshotVersion.min()));
10368
10731
  promises.push(this.documentCache.addEntry(transaction, key, deletedDoc));
10369
10732
  }
10370
10733
  else {
@@ -10445,9 +10808,6 @@ class SchemaConverter {
10445
10808
  * and local feature development.
10446
10809
  */
10447
10810
  createOrUpgrade(db, txn, fromVersion, toVersion) {
10448
- hardAssert(fromVersion < toVersion &&
10449
- fromVersion >= 0 &&
10450
- toVersion <= SCHEMA_VERSION);
10451
10811
  const simpleDbTransaction = new SimpleDbTransaction('createOrUpgrade', txn);
10452
10812
  if (fromVersion < 1 && toVersion >= 1) {
10453
10813
  createPrimaryClientStore(db);
@@ -10514,6 +10874,11 @@ class SchemaConverter {
10514
10874
  createNamedQueriesStore(db);
10515
10875
  });
10516
10876
  }
10877
+ if (fromVersion < 12 && toVersion >= 12) {
10878
+ p = p.next(() => {
10879
+ createFieldIndex(db);
10880
+ });
10881
+ }
10517
10882
  return p;
10518
10883
  }
10519
10884
  addDocumentGlobal(txn) {
@@ -10720,6 +11085,17 @@ function createNamedQueriesStore(db) {
10720
11085
  db.createObjectStore(DbNamedQuery.store, {
10721
11086
  keyPath: DbNamedQuery.keyPath
10722
11087
  });
11088
+ }
11089
+ function createFieldIndex(db) {
11090
+ db.createObjectStore(DbIndexConfiguration.store, {
11091
+ keyPath: DbIndexConfiguration.keyPath
11092
+ });
11093
+ db.createObjectStore(DbIndexState.store, {
11094
+ keyPath: DbIndexState.keyPath
11095
+ });
11096
+ db.createObjectStore(DbIndexEntries.store, {
11097
+ keyPath: DbIndexEntries.keyPath
11098
+ });
10723
11099
  }
10724
11100
 
10725
11101
  /**
@@ -11951,14 +12327,14 @@ function localStoreApplyRemoteEventToLocalCache(localStore, remoteEvent) {
11951
12327
  }
11952
12328
  });
11953
12329
  let changedDocs = mutableDocumentMap();
11954
- remoteEvent.documentUpdates.forEach((key, doc) => {
12330
+ remoteEvent.documentUpdates.forEach(key => {
11955
12331
  if (remoteEvent.resolvedLimboDocuments.has(key)) {
11956
12332
  promises.push(localStoreImpl.persistence.referenceDelegate.updateLimboDocument(txn, key));
11957
12333
  }
11958
12334
  });
11959
12335
  // Each loop iteration only affects its "own" doc, so it's safe to get all the remote
11960
12336
  // documents in advance in a single call.
11961
- promises.push(populateDocumentChangeBuffer(txn, documentBuffer, remoteEvent.documentUpdates, remoteVersion, undefined).next(result => {
12337
+ promises.push(populateDocumentChangeBuffer(txn, documentBuffer, remoteEvent.documentUpdates).next(result => {
11962
12338
  changedDocs = result;
11963
12339
  }));
11964
12340
  // HACK: The only reason we allow a null snapshot version is so that we
@@ -11999,17 +12375,13 @@ function localStoreApplyRemoteEventToLocalCache(localStore, remoteEvent) {
11999
12375
  * Note: this function will use `documentVersions` if it is defined;
12000
12376
  * when it is not defined, resorts to `globalVersion`.
12001
12377
  */
12002
- function populateDocumentChangeBuffer(txn, documentBuffer, documents, globalVersion,
12003
- // TODO(wuandy): We could add `readTime` to MaybeDocument instead to remove
12004
- // this parameter.
12005
- documentVersions) {
12378
+ function populateDocumentChangeBuffer(txn, documentBuffer, documents) {
12006
12379
  let updatedKeys = documentKeySet();
12007
12380
  documents.forEach(k => (updatedKeys = updatedKeys.add(k)));
12008
12381
  return documentBuffer.getEntries(txn, updatedKeys).next(existingDocs => {
12009
12382
  let changedDocs = mutableDocumentMap();
12010
12383
  documents.forEach((key, doc) => {
12011
12384
  const existingDoc = existingDocs.get(key);
12012
- const docReadTime = (documentVersions === null || documentVersions === void 0 ? void 0 : documentVersions.get(key)) || globalVersion;
12013
12385
  // Note: The order of the steps below is important, since we want
12014
12386
  // to ensure that rejected limbo resolutions (which fabricate
12015
12387
  // NoDocuments with SnapshotVersion.min()) never add documents to
@@ -12018,14 +12390,14 @@ documentVersions) {
12018
12390
  // NoDocuments with SnapshotVersion.min() are used in manufactured
12019
12391
  // events. We remove these documents from cache since we lost
12020
12392
  // access.
12021
- documentBuffer.removeEntry(key, docReadTime);
12393
+ documentBuffer.removeEntry(key, doc.readTime);
12022
12394
  changedDocs = changedDocs.insert(key, doc);
12023
12395
  }
12024
12396
  else if (!existingDoc.isValidDocument() ||
12025
12397
  doc.version.compareTo(existingDoc.version) > 0 ||
12026
12398
  (doc.version.compareTo(existingDoc.version) === 0 &&
12027
12399
  existingDoc.hasPendingWrites)) {
12028
- documentBuffer.addEntry(doc, docReadTime);
12400
+ documentBuffer.addEntry(doc);
12029
12401
  changedDocs = changedDocs.insert(key, doc);
12030
12402
  }
12031
12403
  else {
@@ -12279,7 +12651,8 @@ function applyWriteToRemoteDocuments(localStoreImpl, txn, batchResult, documentB
12279
12651
  // We use the commitVersion as the readTime rather than the
12280
12652
  // document's updateTime since the updateTime is not advanced
12281
12653
  // for updates that do not modify the underlying document.
12282
- documentBuffer.addEntry(doc, batchResult.commitVersion);
12654
+ doc.setReadTime(batchResult.commitVersion);
12655
+ documentBuffer.addEntry(doc);
12283
12656
  }
12284
12657
  }
12285
12658
  });
@@ -12380,14 +12753,14 @@ async function localStoreApplyBundledDocuments(localStore, bundleConverter, docu
12380
12753
  const localStoreImpl = debugCast(localStore);
12381
12754
  let documentKeys = documentKeySet();
12382
12755
  let documentMap = mutableDocumentMap();
12383
- let versionMap = documentVersionMap();
12384
12756
  for (const bundleDoc of documents) {
12385
12757
  const documentKey = bundleConverter.toDocumentKey(bundleDoc.metadata.name);
12386
12758
  if (bundleDoc.document) {
12387
12759
  documentKeys = documentKeys.add(documentKey);
12388
12760
  }
12389
- documentMap = documentMap.insert(documentKey, bundleConverter.toMutableDocument(bundleDoc));
12390
- versionMap = versionMap.insert(documentKey, bundleConverter.toSnapshotVersion(bundleDoc.metadata.readTime));
12761
+ const doc = bundleConverter.toMutableDocument(bundleDoc);
12762
+ doc.setReadTime(bundleConverter.toSnapshotVersion(bundleDoc.metadata.readTime));
12763
+ documentMap = documentMap.insert(documentKey, doc);
12391
12764
  }
12392
12765
  const documentBuffer = localStoreImpl.remoteDocuments.newChangeBuffer({
12393
12766
  trackRemovals: true // Make sure document removals show up in `getNewDocumentChanges()`
@@ -12396,7 +12769,7 @@ async function localStoreApplyBundledDocuments(localStore, bundleConverter, docu
12396
12769
  // they will not get garbage collected right away.
12397
12770
  const umbrellaTargetData = await localStoreAllocateTarget(localStoreImpl, umbrellaTarget(bundleName));
12398
12771
  return localStoreImpl.persistence.runTransaction('Apply bundle documents', 'readwrite', txn => {
12399
- return populateDocumentChangeBuffer(txn, documentBuffer, documentMap, SnapshotVersion.min(), versionMap)
12772
+ return populateDocumentChangeBuffer(txn, documentBuffer, documentMap)
12400
12773
  .next(changedDocs => {
12401
12774
  documentBuffer.apply(txn);
12402
12775
  return changedDocs;
@@ -12877,15 +13250,14 @@ class MemoryRemoteDocumentCacheImpl {
12877
13250
  * All calls of `addEntry` are required to go through the RemoteDocumentChangeBuffer
12878
13251
  * returned by `newChangeBuffer()`.
12879
13252
  */
12880
- addEntry(transaction, doc, readTime) {
13253
+ addEntry(transaction, doc) {
12881
13254
  const key = doc.key;
12882
13255
  const entry = this.docs.get(key);
12883
13256
  const previousSize = entry ? entry.size : 0;
12884
13257
  const currentSize = this.sizer(doc);
12885
13258
  this.docs = this.docs.insert(key, {
12886
13259
  document: doc.mutableCopy(),
12887
- size: currentSize,
12888
- readTime
13260
+ size: currentSize
12889
13261
  });
12890
13262
  this.size += currentSize - previousSize;
12891
13263
  return this.indexManager.addToCollectionParentIndex(transaction, key.path.popLast());
@@ -12926,11 +13298,11 @@ class MemoryRemoteDocumentCacheImpl {
12926
13298
  const prefix = new DocumentKey(query.path.child(''));
12927
13299
  const iterator = this.docs.getIteratorFrom(prefix);
12928
13300
  while (iterator.hasNext()) {
12929
- const { key, value: { document, readTime } } = iterator.getNext();
13301
+ const { key, value: { document } } = iterator.getNext();
12930
13302
  if (!query.path.isPrefixOf(key.path)) {
12931
13303
  break;
12932
13304
  }
12933
- if (readTime.compareTo(sinceReadTime) <= 0) {
13305
+ if (document.readTime.compareTo(sinceReadTime) <= 0) {
12934
13306
  continue;
12935
13307
  }
12936
13308
  if (!queryMatches(query, document)) {
@@ -12974,8 +13346,8 @@ class MemoryRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
12974
13346
  applyChanges(transaction) {
12975
13347
  const promises = [];
12976
13348
  this.changes.forEach((key, doc) => {
12977
- if (doc.document.isValidDocument()) {
12978
- promises.push(this.documentCache.addEntry(transaction, doc.document, this.getReadTime(key)));
13349
+ if (doc.isValidDocument()) {
13350
+ promises.push(this.documentCache.addEntry(transaction, doc));
12979
13351
  }
12980
13352
  else {
12981
13353
  this.documentCache.removeEntry(key);
@@ -13288,7 +13660,7 @@ class MemoryEagerDelegate {
13288
13660
  const key = DocumentKey.fromPath(path);
13289
13661
  return this.isReferenced(txn, key).next(isReferenced => {
13290
13662
  if (!isReferenced) {
13291
- changeBuffer.removeEntry(key);
13663
+ changeBuffer.removeEntry(key, SnapshotVersion.min());
13292
13664
  }
13293
13665
  });
13294
13666
  }).next(() => {
@@ -20152,12 +20524,12 @@ async function syncEngineListen(syncEngine, query) {
20152
20524
  }
20153
20525
  else {
20154
20526
  const targetData = await localStoreAllocateTarget(syncEngineImpl.localStore, queryToTarget(query));
20155
- const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
20156
- targetId = targetData.targetId;
20157
- viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
20158
20527
  if (syncEngineImpl.isPrimaryClient) {
20159
20528
  remoteStoreListen(syncEngineImpl.remoteStore, targetData);
20160
20529
  }
20530
+ const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
20531
+ targetId = targetData.targetId;
20532
+ viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
20161
20533
  }
20162
20534
  return viewSnapshot;
20163
20535
  }
@@ -20345,6 +20717,9 @@ async function syncEngineRejectListen(syncEngine, targetId, err) {
20345
20717
  // store to purge a document. However, it would be tricky to keep all of
20346
20718
  // the local store's invariants with another method.
20347
20719
  let documentUpdates = new SortedMap(DocumentKey.comparator);
20720
+ // TODO(b/217189216): This limbo document should ideally have a read time,
20721
+ // so that it is picked up by any read-time based scans. The backend,
20722
+ // however, does not send a read time for target removals.
20348
20723
  documentUpdates = documentUpdates.insert(limboKey, MutableDocument.newNoDocument(limboKey, SnapshotVersion.min()));
20349
20724
  const resolvedLimboDocuments = documentKeySet().add(limboKey);
20350
20725
  const event = new RemoteEvent(SnapshotVersion.min(),
@@ -22289,72 +22664,6 @@ function createBundleReader(data, serializer) {
22289
22664
  return newBundleReader(toByteStreamReader(content), serializer);
22290
22665
  }
22291
22666
 
22292
- /**
22293
- * @license
22294
- * Copyright 2017 Google LLC
22295
- *
22296
- * Licensed under the Apache License, Version 2.0 (the "License");
22297
- * you may not use this file except in compliance with the License.
22298
- * You may obtain a copy of the License at
22299
- *
22300
- * http://www.apache.org/licenses/LICENSE-2.0
22301
- *
22302
- * Unless required by applicable law or agreed to in writing, software
22303
- * distributed under the License is distributed on an "AS IS" BASIS,
22304
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22305
- * See the License for the specific language governing permissions and
22306
- * limitations under the License.
22307
- */
22308
- class DatabaseInfo {
22309
- /**
22310
- * Constructs a DatabaseInfo using the provided host, databaseId and
22311
- * persistenceKey.
22312
- *
22313
- * @param databaseId - The database to use.
22314
- * @param appId - The Firebase App Id.
22315
- * @param persistenceKey - A unique identifier for this Firestore's local
22316
- * storage (used in conjunction with the databaseId).
22317
- * @param host - The Firestore backend host to connect to.
22318
- * @param ssl - Whether to use SSL when connecting.
22319
- * @param forceLongPolling - Whether to use the forceLongPolling option
22320
- * when using WebChannel as the network transport.
22321
- * @param autoDetectLongPolling - Whether to use the detectBufferingProxy
22322
- * option when using WebChannel as the network transport.
22323
- * @param useFetchStreams Whether to use the Fetch API instead of
22324
- * XMLHTTPRequest
22325
- */
22326
- constructor(databaseId, appId, persistenceKey, host, ssl, forceLongPolling, autoDetectLongPolling, useFetchStreams) {
22327
- this.databaseId = databaseId;
22328
- this.appId = appId;
22329
- this.persistenceKey = persistenceKey;
22330
- this.host = host;
22331
- this.ssl = ssl;
22332
- this.forceLongPolling = forceLongPolling;
22333
- this.autoDetectLongPolling = autoDetectLongPolling;
22334
- this.useFetchStreams = useFetchStreams;
22335
- }
22336
- }
22337
- /** The default database name for a project. */
22338
- const DEFAULT_DATABASE_NAME = '(default)';
22339
- /**
22340
- * Represents the database ID a Firestore client is associated with.
22341
- * @internal
22342
- */
22343
- class DatabaseId {
22344
- constructor(projectId, database) {
22345
- this.projectId = projectId;
22346
- this.database = database ? database : DEFAULT_DATABASE_NAME;
22347
- }
22348
- get isDefaultDatabase() {
22349
- return this.database === DEFAULT_DATABASE_NAME;
22350
- }
22351
- isEqual(other) {
22352
- return (other instanceof DatabaseId &&
22353
- other.projectId === this.projectId &&
22354
- other.database === this.database);
22355
- }
22356
- }
22357
-
22358
22667
  /**
22359
22668
  * @license
22360
22669
  * Copyright 2020 Google LLC
@@ -24728,8 +25037,7 @@ class DocumentSnapshot extends DocumentSnapshot$1 {
24728
25037
  this.metadata = metadata;
24729
25038
  }
24730
25039
  /**
24731
- * Property of the `DocumentSnapshot` that signals whether or not the data
24732
- * exists. True if the document exists.
25040
+ * Returns whether or not the data exists. True if the document exists.
24733
25041
  */
24734
25042
  exists() {
24735
25043
  return super.exists();
@@ -25103,51 +25411,53 @@ function limitToLast(limit) {
25103
25411
  return new QueryLimitConstraint('limitToLast', limit, "L" /* Last */);
25104
25412
  }
25105
25413
  class QueryStartAtConstraint extends QueryConstraint {
25106
- constructor(type, _docOrFields, _before) {
25414
+ constructor(type, _docOrFields, _inclusive) {
25107
25415
  super();
25108
25416
  this.type = type;
25109
25417
  this._docOrFields = _docOrFields;
25110
- this._before = _before;
25418
+ this._inclusive = _inclusive;
25111
25419
  }
25112
25420
  _apply(query) {
25113
- const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._before);
25421
+ const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
25114
25422
  return new Query(query.firestore, query.converter, queryWithStartAt(query._query, bound));
25115
25423
  }
25116
25424
  }
25117
25425
  function startAt(...docOrFields) {
25118
- return new QueryStartAtConstraint('startAt', docOrFields, /*before=*/ true);
25426
+ return new QueryStartAtConstraint('startAt', docOrFields,
25427
+ /*inclusive=*/ true);
25119
25428
  }
25120
25429
  function startAfter(...docOrFields) {
25121
25430
  return new QueryStartAtConstraint('startAfter', docOrFields,
25122
- /*before=*/ false);
25431
+ /*inclusive=*/ false);
25123
25432
  }
25124
25433
  class QueryEndAtConstraint extends QueryConstraint {
25125
- constructor(type, _docOrFields, _before) {
25434
+ constructor(type, _docOrFields, _inclusive) {
25126
25435
  super();
25127
25436
  this.type = type;
25128
25437
  this._docOrFields = _docOrFields;
25129
- this._before = _before;
25438
+ this._inclusive = _inclusive;
25130
25439
  }
25131
25440
  _apply(query) {
25132
- const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._before);
25441
+ const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
25133
25442
  return new Query(query.firestore, query.converter, queryWithEndAt(query._query, bound));
25134
25443
  }
25135
25444
  }
25136
25445
  function endBefore(...docOrFields) {
25137
- return new QueryEndAtConstraint('endBefore', docOrFields, /*before=*/ true);
25446
+ return new QueryEndAtConstraint('endBefore', docOrFields,
25447
+ /*inclusive=*/ false);
25138
25448
  }
25139
25449
  function endAt(...docOrFields) {
25140
- return new QueryEndAtConstraint('endAt', docOrFields, /*before=*/ false);
25450
+ return new QueryEndAtConstraint('endAt', docOrFields, /*inclusive=*/ true);
25141
25451
  }
25142
25452
  /** Helper function to create a bound from a document or fields */
25143
- function newQueryBoundFromDocOrFields(query, methodName, docOrFields, before) {
25453
+ function newQueryBoundFromDocOrFields(query, methodName, docOrFields, inclusive) {
25144
25454
  docOrFields[0] = getModularInstance(docOrFields[0]);
25145
25455
  if (docOrFields[0] instanceof DocumentSnapshot$1) {
25146
- return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, before);
25456
+ return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, inclusive);
25147
25457
  }
25148
25458
  else {
25149
25459
  const reader = newUserDataReader(query.firestore);
25150
- return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, before);
25460
+ return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, inclusive);
25151
25461
  }
25152
25462
  }
25153
25463
  function newQueryFilter(query, methodName, dataReader, databaseId, fieldPath, op, value) {
@@ -25205,7 +25515,7 @@ function newQueryOrderBy(query, fieldPath, direction) {
25205
25515
  * of the query or if any of the fields in the order by are an uncommitted
25206
25516
  * server timestamp.
25207
25517
  */
25208
- function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
25518
+ function newQueryBoundFromDocument(query, databaseId, methodName, doc, inclusive) {
25209
25519
  if (!doc) {
25210
25520
  throw new FirestoreError(Code.NOT_FOUND, `Can't use a DocumentSnapshot that doesn't exist for ` +
25211
25521
  `${methodName}().`);
@@ -25242,12 +25552,12 @@ function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
25242
25552
  }
25243
25553
  }
25244
25554
  }
25245
- return new Bound(components, before);
25555
+ return new Bound(components, inclusive);
25246
25556
  }
25247
25557
  /**
25248
25558
  * Converts a list of field values to a `Bound` for the given query.
25249
25559
  */
25250
- function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, before) {
25560
+ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, inclusive) {
25251
25561
  // Use explicit order by's because it has to match the query the user made
25252
25562
  const orderBy = query.explicitOrderBy;
25253
25563
  if (values.length > orderBy.length) {
@@ -25284,7 +25594,7 @@ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, valu
25284
25594
  components.push(wrapped);
25285
25595
  }
25286
25596
  }
25287
- return new Bound(components, before);
25597
+ return new Bound(components, inclusive);
25288
25598
  }
25289
25599
  /**
25290
25600
  * Parses the given `documentIdValue` into a `ReferenceValue`, throwing
@@ -26268,17 +26578,6 @@ function writeBatch(firestore) {
26268
26578
  ensureFirestoreConfigured(firestore);
26269
26579
  return new WriteBatch(firestore, mutations => executeWrite(firestore, mutations));
26270
26580
  }
26271
- /** An index component consisting of field path and index type. */
26272
- class Segment {
26273
- constructor(
26274
- /** The field path of the component. */
26275
- fieldPath,
26276
- /** The fields sorting order. */
26277
- kind) {
26278
- this.fieldPath = fieldPath;
26279
- this.kind = kind;
26280
- }
26281
- }
26282
26581
 
26283
26582
  /**
26284
26583
  * @license
@@ -26302,27 +26601,29 @@ function setIndexConfiguration(firestore, jsonOrConfiguration) {
26302
26601
  const indexConfiguration = typeof jsonOrConfiguration === 'string'
26303
26602
  ? tryParseJson(jsonOrConfiguration)
26304
26603
  : jsonOrConfiguration;
26604
+ const parsedIndexes = [];
26305
26605
  // PORTING NOTE: We don't return an error if the user has not enabled
26306
26606
  // persistence since `enableIndexeddbPersistence()` can fail on the Web.
26307
26607
  if (Array.isArray(indexConfiguration.indexes)) {
26308
26608
  for (const index of indexConfiguration.indexes) {
26309
- tryGetString(index, 'collectionGroup');
26609
+ const collectionGroup = tryGetString(index, 'collectionGroup');
26310
26610
  const segments = [];
26311
26611
  if (Array.isArray(index.fields)) {
26312
26612
  for (const field of index.fields) {
26313
26613
  const fieldPathString = tryGetString(field, 'fieldPath');
26314
26614
  const fieldPath = fieldPathFromDotSeparatedString('setIndexConfiguration', fieldPathString);
26315
26615
  if (field.arrayConfig === 'CONTAINS') {
26316
- segments.push(new Segment(fieldPath, 2 /* CONTAINS */));
26616
+ segments.push(new IndexSegment(fieldPath, 2 /* CONTAINS */));
26317
26617
  }
26318
26618
  else if (field.order === 'ASCENDING') {
26319
- segments.push(new Segment(fieldPath, 0 /* ASCENDING */));
26619
+ segments.push(new IndexSegment(fieldPath, 0 /* ASCENDING */));
26320
26620
  }
26321
26621
  else if (field.order === 'DESCENDING') {
26322
- segments.push(new Segment(fieldPath, 1 /* DESCENDING */));
26622
+ segments.push(new IndexSegment(fieldPath, 1 /* DESCENDING */));
26323
26623
  }
26324
26624
  }
26325
26625
  }
26626
+ parsedIndexes.push(new FieldIndex(FieldIndex.UNKNOWN_ID, collectionGroup, segments, IndexState.empty()));
26326
26627
  }
26327
26628
  }
26328
26629
  // TODO(indexing): Configure indexes